skip to content

How do whole-route hydration, islands-only hydration, and shipping no client script differ in what a route downloads?

level: middleimportance: must knowfreq 68%

answer

  1. the same HTML, three different second deliveries
  2. payload tracks page size or interactivity
  3. islands leave the rest inert HTML
  4. no script means platform behaviour only
  5. narrower scope, harder state sharing

basics

~20 s

Scope decides the script budget. Whole-route hydration ships the route's entire component tree; islands ship only the parts declared interactive and leave the rest as inert HTML; a no-script route ships none, so only platform behaviour works.

solid answer

~50 s

All three serve the same finished HTML — they differ in how much code has to arrive afterwards. **Whole-route hydration** hands the client the route's whole component tree, because any node might need behaviour; the payload tracks the size of the page, not the size of its interactivity. **Islands-only hydration** treats the page as static HTML with a few declared interactive regions: each region ships its own code, and everything else never becomes a component in the browser. **Shipping no client script** is the floor — links, forms and CSS still work because the browser implements them, and anything else has to be re-expressed in those terms or dropped. The tradeoff is not only bytes: narrower scope means less main-thread work and better behaviour when script fails, but an interactive part can no longer share live state with the rest of the page.

go deeper

for a junior

Know the three positions by name and by payload: everything, only the declared interactive parts, or nothing. Remember that the HTML the user first sees is the same in all three.

for a middle

Explain why whole-route scope scales with page size while islands scale with interactivity, and name what islands cost the author — an explicit boundary and no shared in-tree state.

for a senior

Show that you test the failure mode: what a route still does when its bundle never loads, and how scope silently widens when an interactive element lands in a shared shell.

for a principal

Own the policy: which scope is the default, what evidence justifies widening it, and how much authoring constraint the team accepts in exchange for payload and resilience.

## The one decision behind the payload Every server-rendered route pays two deliveries: the HTML, then whatever script and state let the client take that HTML over. **Scope** is the choice of how much of the route participates in the second delivery, and it is the single biggest lever on a route's script budget. ## Whole-route hydration The client is handed the component tree for the entire route and re-renders it to attach behaviour everywhere. - **What ships:** every component the route renders, plus the shared framework runtime, plus the state the render depended on. - **Why:** the framework makes no distinction between an interactive control and a paragraph of prose — both are components, so both must exist in the browser. - **Consequence:** payload and main-thread work scale with **page size**, not with how interactive the page is. A long article with one subscribe button can cost as much as an editor. - **What it buys:** uniformity. Any component may hold state, read context, or be swapped during a client-side navigation, and authors need no ceremony to make something interactive. ## Progressive or deferred hydration A middle position that keeps whole-route scope but moves *when* the work happens — takeover is scheduled at browser idle, on visibility, or on first interaction. It reduces contention around first paint but does not by itself shrink what the route must eventually download. ## Islands-only hydration The route is treated as static HTML containing a few explicitly declared interactive regions. - **What ships:** only the code for the declared regions plus the runtime they need; the surrounding markup never becomes a component in the browser. - **Consequence:** payload scales with **how much is interactive**, which on content-shaped pages is a small fraction of the page. - **Cost to the author:** the boundary is explicit and has to be drawn, and it is a real barrier. Two islands are separate client trees; sharing live state across them means an explicit channel rather than ordinary in-tree state, and an island cannot reach up to re-render its non-interactive surroundings. ## No client script The floor. The route ships HTML and CSS and nothing else. - **What works:** everything the browser implements — links, plain form submission, CSS transitions and native form validation, the back button. - **What does not:** anything whose behaviour is defined in application code. - **Where it fits:** pages whose job is to be read, and flows that can be expressed as navigations and form posts rather than in-place updates. ## Side by side | Scope | Script the route downloads | Interactive after takeover | If script fails or is blocked | Author burden | |---|---|---|---|---| | Whole route | Tree for the whole page | Everything | Page is readable, nothing responds | Lowest | | Deferred whole route | Same, later or split | Everything, in stages | Same as whole route | Low | | Islands only | Declared regions only | Those regions | Everything but the islands still works | Boundaries must be drawn | | No client script | None | Nothing scripted | Nothing is lost | Flows must be re-expressed | ## What actually differs, and what does not What differs: bytes on the wire, main-thread time before the route responds, how much of the page survives a failed or blocked bundle, and how freely components may share state. What does **not** differ: the HTML. All three can produce the same server-rendered markup and the same first paint, which is why first-paint metrics alone will not tell these approaches apart. The difference shows up in the gap between the page appearing and the page responding — and, when the bundle never arrives, in whether anything responds at all. ## Where frameworks differ Meta-frameworks sit at different defaults along this spectrum. Some hydrate whole routes unless told otherwise and offer per-component deferral as an optimisation; others treat static output as the default and require an explicit marker before any region ships code; a few can serialise enough state that the client resumes rather than re-executing the render. Many now mix modes within one route, which is why scope is better read per route from the build output than assumed from the framework's reputation. ## Choosing, in practice 1. Start from what the route genuinely does: reading, or operating. 2. Prefer the narrowest scope that supports the interactions the page actually has. 3. Check what the page does with script disabled — that failure mode is the honest test of how much you leaned on hydration. 4. Re-check per route as features land, because interactivity added in a shared shell widens scope for every page under it.

  • Why can a mostly static page still pay a large hydration cost under whole-route scope?
    Because scope is decided per route, not per node. If the route's tree must exist in the browser, every component in it ships, whether or not it has behaviour. The prose, the layout chrome and the footer are components too, so the budget follows how much page there is rather than how much of it responds.
  • What do you give up by splitting a page into islands?
    Shared live state and free composition. Each island is its own client tree, so state that spans two of them needs an explicit channel, and an island cannot re-render the static markup around it. You also take on drawing and maintaining the boundary, which is a design decision rather than a default.
  • Does narrowing hydration scope improve the first paint?
    Usually not much — the HTML is the same, so the paint is the same. What narrows is the gap between paint and the page responding, and the main-thread work competing with early interaction. Judge scope by interactivity readiness and payload, not by first paint.

saying these in an interview costs you the question

  • Assumes narrower hydration scope speeds up first paint
  • Thinks islands are just code splitting by another name
  • Believes whole-route hydration only ships the interactive components
  • Says a no-script route cannot accept user input at all
  • Ignores that islands cannot share in-tree state freely
  • Treats the framework's default scope as the only option per route