What is Hydration? 💧
In the context of modern web frameworks (like React, Vue, or Svelte), Hydration is the process of using client-side JavaScript to add application state and interactivity to server-rendered HTML.
When you use SSR or SSG, the server sends a static HTML snapshot of your application. It looks complete, but it's just a painting—buttons don't work, forms don't submit, and dropdowns don't open.
Hydration is the "waking up" process:
- The browser loads the HTML (FCP).
- The browser loads the JavaScript bundle.
- React executes the JavaScript to reconstruct the component tree in memory.
- React attaches event listeners (click, submit, etc.) to the existing DOM nodes.
Only after step 4 is your application actually interactive (Time to Interactive - TTI).
The "Uncanny Valley" Problem
The gap between seeing the content (First Contentful Paint) and being able to interact with it (Time to Interactive) is known as the Uncanny Valley.
Imagine a user sees a "Buy Now" button instantly because of SSR. They try to click it, but nothing happens because the JavaScript hasn't finished downloading and hydrating. This leads to:
- Rage Clicks: Users clicking repeatedly in frustration.
- Broken Experience: The site feels "heavy" or "laggy" despite looking fast.
The more JavaScript you have, the longer this hydration process takes, and the wider this valley becomes.
Partial Hydration (Islands Architecture) 🏝️
The solution to the heavy cost of hydration is Partial Hydration, often implemented via the Islands Architecture.
Instead of hydrating the entire page (which React traditionally does), frameworks like Astro or Fresh treat the page as static HTML by default. You then explicitly mark small "islands" of interactivity that need to be hydrated.
How it Works
Imagine a blog post page:
- Header & Footer: Static HTML (No JS).
- Article Text: Static HTML (No JS).
- Sidebar: Static HTML (No JS).
- "Like" Button: Interactive Island (Hydrated).
- Comment Section: Interactive Island (Hydrated).
In this model, 90% of your page sends 0KB of JavaScript to the client. The browser only downloads and executes JS for the "Like" button and comments.
Visualizing Islands
// Hypothetical Islands Implementation
// ❌ Traditional React (Hydrates EVERYTHING)
export default function Page() {
return (
<Layout>
<Header /> {/* Hydrated */}
<Sidebar /> {/* Hydrated */}
<MainContent /> {/* Hydrated */}
<Footer /> {/* Hydrated */}
</Layout>
);
}
// ✅ Islands Architecture (Hydrates ONLY Interactive Parts)
export default function Page() {
return (
<Layout>
<Header /> {/* Static HTML */}
<Sidebar /> {/* Static HTML */}
<MainContent /> {/* Static HTML */}
{/* Only this specific component ships JS to the browser */}
<LikeButton client:load />
<Footer /> {/* Static HTML */}
</Layout>
);
}Progressive Hydration vs. Partial Hydration
It's important to distinguish between these two optimization techniques:
Progressive Hydration
- Goal: Prioritize what gets hydrated first.
- Mechanism: The entire page will eventually be hydrated, but we start with the most critical components (e.g., the viewport) to make them interactive sooner.
- Used by: Next.js, React Concurrent Mode.
Partial Hydration
- Goal: Reduce how much gets hydrated.
- Mechanism: Parts of the page are never hydrated at all. They remain static HTML forever.
- Used by: Astro, 11ty, Fresh.
The Future: Resumability ⏩
The next evolution beyond hydration is Resumability (pioneered by Qwik).
In hydration, the framework has to re-execute all the logic in the browser to "understand" where event listeners belong. Resumability serializes the event listeners and state directly into the HTML.
When you click a button in a Resumable app, a tiny piece of JS intercepts the click, downloads only the specific function needed for that handler, and runs it. There is no hydration step at initialization. The app is interactive instantly, with effectively zero startup JS.
Conclusion
Hydration was a necessary bridge to bring the interactivity of SPAs to server-rendered content. However, as web applications grow heavier, the cost of re-running everything in the browser has become a bottleneck.
Techniques like Partial Hydration and Resumability are shifting the paradigm back towards HTML-first, sending JavaScript only when and where it is absolutely necessary.