Hydration vs Prerendering
Server-rendered HTML gets content to the screen fast, but the page is not interactive until JavaScript arrives. Prerendered HTML gets to the screen even faster, because there is no server waiting on a request. Both strategies look similar to the user on first glance, yet they differ in cost, in flexibility, and in the work the browser still has to do. Understanding hydration and prerendering precisely, rather than as buzzwords, is what lets you make the decision deliberately.
This guide follows on from CSR vs SSR and provides the detail behind two of the most commonly confused techniques in modern frontend rendering.
What you'll learn
How full hydration works
Full hydration is what most SSR frameworks do by default. The server renders HTML; the client re-runs the same component tree in JavaScript to attach interactivity.
Walking the server-rendered DOM
// React SSR: server renders to string
var html = ReactDOM.renderToString(<App data={data} />);
// Client hydrates the same tree
ReactDOM.hydrateRoot(
document.getElementById('root'),
<App data={data} />
);
The framework walks the existing DOM, matches nodes to the virtual tree it would produce, and attaches event listeners in place rather than replacing markup. If the server-rendered HTML matches what the client would render, hydration is clean. If they differ, a mismatch error appears and the framework falls back to a full re-render, defeating the purpose of SSR entirely. Keeping server and client state identical at hydration time is more subtle than it sounds: timestamps, random IDs, browser-only globals all introduce mismatches.
The hidden cost of hydration
Pages that use SSR often feel slower to interact with than expected, even when LCP is fast. The culprit is almost always the hydration step itself.
The visible-but-not-interactive gap
After HTML paints, the browser still has to download the JavaScript bundle, parse it, execute it, and walk the DOM to attach listeners. On a low-end device with a slow connection, that can take several seconds. During that time the page looks ready but taps and clicks do nothing, which is a confusing and frustrating experience. The gap between Largest Contentful Paint and Time to Interactive is the price of full hydration. Shrinking the JavaScript bundle and deferring non-critical hydration are the two levers.
Partial and progressive hydration
Instead of hydrating the entire page at once, smarter strategies hydrate only the parts that need it, and only when they need it.
Islands of interactivity
<!-- Astro island: only this component ships JavaScript -->
<SearchWidget client:visible />
<!-- Everything else is static HTML, no JS sent -->
<ArticleBody />
The islands architecture, used by Astro and similar tools, treats interactive components as isolated islands in a sea of static HTML. Only the island components receive JavaScript; the rest of the page is plain markup. Progressive hydration takes a similar approach but within a single framework: components hydrate in priority order, above-the-fold first, deferring off-screen or low-priority islands until the user scrolls to them or interacts. Both approaches shrink the initial JavaScript that must execute before the page is interactive, which directly improves Time to Interactive and Core Web Vitals.
Static prerendering at build time
Prerendering sidesteps the request-time server entirely. Pages are generated once, stored as HTML files, and served from a CDN edge node close to the user.
Build-time HTML generation
// Next.js static generation: runs at build time, not per request
export async function getStaticProps() {
var posts = await fetchPosts();
return { props: { posts } };
}
There is no server to wait on, no render to perform, and no TTFB to optimise beyond the CDN's own latency, which is typically under fifty milliseconds globally. For content that can be determined ahead of time, articles, documentation, marketing pages, this is the fastest possible delivery. The constraint is that content must be known at build time. User-specific data, session state, or real-time feeds require either a subsequent client-side fetch or a revalidation strategy that rebuilds the static file periodically.
Resumability: skipping hydration
A newer approach questions whether hydration needs to happen at all. Resumability serialises the component state into the HTML so the framework can pick up exactly where the server left off.
Serialised state and lazy execution
Frameworks like Qwik encode event listeners and component state directly into the HTML as attributes. When a user taps a button, only the code for that specific handler downloads and runs. The rest of the page never hydrates unless it is interacted with. This eliminates the startup cost of full hydration entirely and makes Time to Interactive nearly equal to LCP regardless of application size. The trade-off is a new programming model and more data in the initial HTML. Resumability is early-stage in production use, but it points toward where hydration is heading.
Choosing a strategy
The choice is not binary. Real applications mix strategies per route based on what each page actually needs.
Matching the strategy to the content
Use full hydration when every part of the page is interactive and personalised. Use partial hydration or islands when most of a page is static but a few components need JavaScript. Use static prerendering for content that changes rarely and can be rebuilt on a schedule. Use progressive hydration to prioritise above-the-fold interactivity and defer the rest. The throughline is the same principle that runs through the whole rendering cluster: do the minimum work necessary in the browser, as late as possible, for the content that is actually on screen.
Frequently Asked Questions
What is hydration in web development?
Hydration is the process where JavaScript takes over server-rendered HTML by attaching event listeners and recreating component state. The page looks complete before hydration but is not interactive until the JavaScript bundle downloads and executes.
What is prerendering?
Prerendering generates static HTML at build time rather than at request time. Each URL becomes a plain HTML file that a CDN can serve instantly. It is the fastest possible load for content that does not change per user or per request.
What is partial hydration?
Partial hydration, also called the islands architecture, only hydrates the interactive components on a page. Static content stays as plain HTML and never receives JavaScript. This keeps the JavaScript payload small and Time to Interactive low.
What is the difference between SSG and SSR?
Static site generation renders pages once at build time and serves them as files. Server-side rendering generates HTML on the server for each incoming request. SSG is faster to serve and cheaper to host but only suits content that can be determined ahead of time.
Read next: the Rendering hub, or revisit CSR vs SSR for the broader rendering strategy picture.
Want a rendering approach with no hydration overhead?
The Backbone guide shows direct DOM rendering with no virtual DOM and no hydration step.
Explore the Backbone Guide →