Rehydration (also known as universal rendering, isomorphic rendering, or SSR with client-side hydration) is a trending technique being used heavily by JavaScript frameworks when it promises to combine the strengths of both server-side rendering (SSR) and client-side rendering (CSR) to make your web apps fast, SEO friendly, and highly interactive.
Sounds like an ideal technique, right? Let’s dig deeper to see how it works, how it performs compare to other rendering techniques, and in which situation it really excels.
Basic understanding of how SSR and CSR work is expected because this technique combines the best of both; a key takeaway is that SSR excels at SEO performance and CSR excels at interactivity.
Hydration refers to filling an existing object with data. It is not a synonym for serialization. It is not a synonym for deserialization either. Deserialization involves creating the object with the data it had at the time it was serialized. Hydration refers to how you fill an object with data. Hydration is also used when discussing plans for loading data from databases or other data sources to construct application.
You could say that an object is partially hydrated when you have only loaded some of the fields into it, but not all of them.
All modern JavaScript frameworks construct and maintain an internal representation (known as Virtual DOM) to do fancy stuff and sync with browser DOM over time. This Virtual DOM thing is just a JavaScript object kept in memory, highly dynamic and cheap to update, can be built both on server or browser, can be serialized and transferred over the internet, and of course can be hydrated again from string representation.
This post talks about rehydration as a rendering technique where client-side JavaScript framework takes over the static HTML sent by the server and turns it into dynamic DOM that can react to client-side data changes.
Server-side generated HTML content also embeds all necessary data, this static HTML can then be enhanced with client-side JavaScript via rehydration. Mismatch assertion can be implemented differently betweens frameworks and working modes.
In React, if there is a mismatch, it will bail hydration, discard existing DOM and render from scratch. In production mode, this assertion is disabled for maximum performance.
Rehydration is very SEO friendly like SSR when complete HTML markup already generated on server, it also delivers very good perceived performance, and solid first contentful pain on a wide range of devices.
One catch is the confusion caused by perceived performance and delayed interactivity, your sites often look deceptively loaded and interactive, but can’t actually respond to input until the client-side JS is executed and event handlers have been attached. This can take seconds or even minutes on mobile.
Another catch is high level of duplication in HTML content — In order for the client-side JavaScript to be able to accurately pick up where the server left off without having to re-request all of the data the server used to render its HTML, current SSR solutions generally serialize the response from a UI’s data dependencies into the document as script tags.
Rehydration also poses some challenges for caching, navigation, special HTML structures altered by browsers.
To overcome the downside of delayed interactivity, many variations to fully rehydration was proposed to only rehydrate some parts of the page.
Progressive rehydration — individual pieces of a server-rendered application are booted up over time, rather than the current common approach of initializing the entire application at once.
Partial rehydration — an extension of the idea of progressive rehydration, where the individual pieces (components / views / trees) to be progressively rehydrated are analyzed and those with little interactivity or no reactivity are identified.
Lazy hydration — delay the hydration of pre-rendered HTML util it needed.
Above solutions are not only hard to implement in JavaScript frameworks but also need hints from developers to perform properly.
When you use a JavaScript framework on server to generate static HTML markup, you also want to use that framework on client-side to take advantage of highly interactivity feature and create a truly universal codebase that works seamlessly from server to client.
But above assumption happens in an ideal world, in reality rehydration solution seem more complex than pure SSR or CSR when some parts of your code only work on server and some parts only work on browser.
You also need to pick 3rd-party libraries carefully when some don’t work properly with rehydration, especially those developed purely for CSR.
You can implement rehydration yourself using any JavaScript frameworks that have server APIs but not recommended even for veteran developers. You should use a higher-level solution that provides a smooth out-of-the-box experience.
Next.js is the best React framework that implements rehydration, it is matured, battle-tested, has plenty examples, simple to use and tons of other features; definitely check it out if you’re using React and also want SSR.
Nuxt.js is the go-to Vue framework that works similar to Next.js. It’s built upon the same Vue stack but abstracts away a lot of the boilerplate, and provides some extra features such as static site generation.
Modern web development uses JavaScript frameworks, rehydration is a natural enhancement from pure SSR when you also use that framework on browser. It’s not perfect but it has a place!