# Hydration Strategies & Islands > Pay JS cost only for interactive regions, not the whole page. Frontend architecture guidance from fearchitect, written by Abas Turabli and last reviewed 2026-06-21. Source: https://fearchitect.com/topics/hydration-and-islands Use it as reference for the task at hand. Before changing code, check this guidance against the codebase: where the code already makes a different, deliberate choice, flag the conflict instead of rewriting it. Library APIs move faster than this guide, so confirm exact signatures in the official docs linked at the end. ## Summary Full hydration re-executes React for every node in the server-rendered tree — wasted work on static content. Selective, progressive, and lazy hydration reduce that cost. Islands architecture takes it further: ship a fully static page, then hydrate each interactive widget in isolation. The result is faster TTI and less main-thread blocking on content-heavy pages. ## Hydration **Hydration** is the step after SSR where the browser attaches React's event system to server-rendered HTML. Full hydration does this for the entire tree up-front — wasted work on static content. **Selective hydration** (React 18): each ``-wrapped subtree hydrates independently; React prioritises whichever the user clicks first. **Progressive/lazy hydration** defers non-critical subtrees until idle or visible via `IntersectionObserver` + dynamic `import()`. **Islands architecture** (Astro, Fresh) goes further: the page is static HTML and only explicitly marked components carry their own JS bundle. ## Hydration strategies at a glance | Strategy | JS shipped | When hydrates | Framework | | --- | --- | --- | --- | | **Full hydration** | Whole tree | Page load | React / Vue | | **Selective hydration** | Whole tree | Per Suspense boundary | React 18 | | **Islands (client:visible)** | Per island only | On viewport entry | Astro / Fresh | | **RSC** | Zero client JS | Never (server only) | Next.js App Router | ## Astro island with client:visible Zero JS ships by default in Astro. Add a `client:` directive to opt an island into hydration. ```astro --- // src/pages/index.astro import HeroImage from "../components/HeroImage.astro"; // static, zero JS import CommentSection from "../components/CommentSection"; // React island --- ``` `client:visible` uses IntersectionObserver; island JS loads only when it enters the viewport. HeroImage is plain Astro — no JS ships for it. ## Diagram ```mermaid flowchart LR subgraph Page["Static HTML page"] A[Static header] --> B[Static article] B --> C["Island: CommentSection (client:visible)"] B --> D["Island: ShareWidget (client:idle)"] end C -->|"IntersectionObserver fires"| E["Load island JS + hydrate"] D -->|"requestIdleCallback"| F["Load island JS + hydrate"] ``` Static page ships zero JS; each island loads and hydrates only when its trigger fires. ## Watch out: next/dynamic with ssr: false requires a Client Component In Next.js App Router, `dynamic(() => import('./Component'), { ssr: false })` is not allowed in Server Components. Wrap the `dynamic` call in a file marked `"use client"` and import that wrapper into your Server Component tree instead. ## Key terms - **Hydration**: Attaching React's event system to server-rendered HTML so it becomes interactive. - **Islands architecture**: Static-HTML page with isolated interactive components that each carry their own JS bundle. - **client:visible**: Astro directive that hydrates an island only when it enters the viewport via IntersectionObserver. - **Hydration mismatch**: Server HTML differs from client render; React discards SSR work and re-renders from scratch. - **Selective hydration**: React 18 feature: Suspense subtrees hydrate independently; user interaction prioritises which hydrates first. ## Related topics - [React Server Components](https://fearchitect.com/topics/react-server-components.md): Server-rendered components that ship zero JS to the browser. - [Resumability (Qwik)](https://fearchitect.com/topics/resumability-qwik.md): Skip hydration by serializing state and listeners directly into HTML. - [Streaming SSR](https://fearchitect.com/topics/streaming-ssr.md): Flush the HTML shell immediately, then stream the rest as Suspense resolves. - [Rendering Strategies: CSR / SSR / SSG / ISR](https://fearchitect.com/topics/rendering-strategies.md): Where and when HTML is generated: build, request, browser, or revalidated. - [Partial Prerendering (PPR)](https://fearchitect.com/topics/partial-prerendering.md): Static CDN shell plus dynamic Suspense holes in one response. ## Further reading - [Astro — Client-side scripts & islands](https://docs.astro.build/en/guides/client-side-scripts/) - [Astro — client: directives reference](https://docs.astro.build/en/reference/directives-reference/#client-directives) - [React — Selective hydration with Suspense](https://react.dev/reference/react-dom/client/hydrateRoot) - [Islands Architecture — Jason Miller](https://jasonformat.com/islands-architecture/)