Hydration

On this page 7

Hydration is the process in which a JavaScript framework running in the browser takes over HTML that was already rendered on the server or at build time, rebuilds its component tree in memory and attaches event handlers and state so the page becomes interactive. In web applications, it connects server-side rendering with the dynamic behavior of a client-side application.

The server-rendered markup lets users see content quickly, while hydration makes that content respond to clicks and input. The gap between the two moments, and the JavaScript cost of closing it, is the central performance question of modern rendering architectures.

How hydration turns static markup into an application

Hydration starts after the browser has parsed the server HTML and downloaded the application bundle. The framework runs the same components that produced the HTML, but instead of creating new DOM nodes it walks the existing DOM and pairs each node with its virtual or reactive counterpart.

  1. The server renders HTML and embeds serialized data, often as a JSON script block.
  2. The browser paints the HTML, so content is visible before any JavaScript runs.
  3. The bundle downloads and executes, recreating component state from the serialized data.
  4. The framework reconciles its expected output with the existing DOM and attaches listeners.
  5. The page becomes interactive, and later updates are handled entirely on the client.

The critical assumption is that server and client render identical output for the same data. When they differ, the framework reports a hydration mismatch and either patches the difference or discards the server markup and renders the subtree again, which costs time and can cause visible flicker.

Hydration strategies and their trade-offs

Classic full hydration processes the entire page in one pass, even parts that never change. Newer strategies reduce that cost by hydrating less, later or in smaller pieces.

StrategyHow it worksMain benefit
Full hydrationHydrates the whole component tree at onceSimple model, broad framework support
Progressive hydrationHydrates components over time or on visibilityShorter main-thread blocks at startup
Selective hydrationHydrates Suspense boundaries independently, prioritizing user inputInteractive regions respond sooner
Partial hydration (islands)Ships JavaScript only for interactive islandsFar less JavaScript on content pages
ResumabilitySerializes listeners and state so no replay is neededNear-zero startup execution
Server componentsNon-interactive components never ship to the clientSmaller bundles and less hydration work
Main hydration strategies

The right strategy depends on how much of the page is interactive. A dashboard that is interactive almost everywhere gains little from islands, while a content site with a single search box and a menu can avoid most hydration entirely.

Hydration among rendering approaches

Hydration exists only where HTML is produced before the client application runs. It is therefore part of SSR and SSG setups and is absent in pure client-side rendering, where the browser builds the DOM from scratch.

ApproachWhere HTML is producedRole of hydration
Client-side renderingIn the browser at runtimeNone; the client builds the DOM itself
SSROn the server per requestRequired to make the page interactive
SSGAt build timeRequired for any interactive parts
MPA without a frameworkOn the serverUsually none; small scripts enhance pages
SPA with SSRServer for the first view, client afterwardRuns once, then client routing takes over
Rendering approaches and the role of hydration

A PWA can use any of these approaches; hydration concerns the first render of a document, while a service worker and caching concern how its resources are delivered.

Performance effects of hydration

Hydration shifts the bottleneck from network and server to the main thread. Server rendering improves FCP and LCP because content arrives in the HTML, but hydration can produce long tasks of hundreds of milliseconds on mid-range phones, which hurts INP and Total Blocking Time.

SymptomLikely causeRemedy
Clicks ignored after loadButtons visible before handlers attachSelective or progressive hydration
Long startup tasksEntire tree hydrated in one passSplit boundaries, defer offscreen parts
Large HTML documentsData serialized twice, in markup and JSONSend only data the client needs
Flicker after loadHydration mismatch forces re-renderMake rendering deterministic
Slow time to interactiveBig bundles on slow networksCode splitting, server components
Symptoms caused by hydration and their remedies

The period in which a page looks ready but does not respond is sometimes called the uncanny valley of server rendering. It is the most user-visible hydration cost and the main motivation for selective and resumable approaches.

Common causes of hydration mismatches

Mismatches come from non-deterministic rendering: any value that differs between the server run and the client run. Most are avoidable once developers know the usual sources.

  • Dates and times formatted with different time zones or locales on server and client.
  • Random values such as generated IDs created separately on each side.
  • Browser-only APIs like window size or localStorage read during the initial render.
  • Invalid HTML nesting, such as a div inside a p, which the parser silently restructures.
  • Browser extensions that inject markup before the framework hydrates.

The standard fix is to render a stable placeholder on both sides and apply client-only values in an effect that runs after hydration, so the first client render matches the server output exactly.

The idea in brief

Think of a shop window display that arrives fully arranged, so passers-by can look at it immediately. Hydration is the moment a staff member steps in and connects the display to the till and the lights, so that touching things actually does something.

Before hydration, a web page can look finished but buttons do nothing. After hydration, the page works like a full application. The challenge is making that switch quick and invisible to the visitor.

A practical scenario

An online retailer renders its product pages on the server, and they appear in about 1.5 seconds on a typical phone. Analytics show many shoppers tapping the add to cart button repeatedly, because nothing happens for almost two more seconds while the full page hydrates.

The team profiles startup and finds that reviews, recommendations and the footer are hydrated before the purchase form. They wrap those sections in separate boundaries, hydrate them when they scroll into view and convert the static product description to a server component that ships no JavaScript.

The purchase controls now become interactive within a few hundred milliseconds of first paint. Repeated taps disappear from the analytics, the main-thread startup work shrinks substantially, and the measured INP for the page moves into the good range.