Implement partial hydration in Next.js using client component boundaries, dynamic imports with SSR, and third-party libraries like next-lazy-hydrate to defer hydration of non-critical UI islands
Partial hydration and Islands Architecture represent a shift from monolithic client-side applications to a model where most of the page is static HTML, with only isolated interactive 'islands' that hydrate independently. In Next.js, you can implement this pattern through a combination of built-in features: React Server Components for static content, Client Components with strategic 'use client' boundaries, dynamic imports with SSR disabled, and libraries that provide granular control over when and how components hydrate. The goal is to reduce JavaScript execution during page load, improving metrics like Time to Interactive (TTI) and First Input Delay (FID).
Core concept: A page is primarily server-rendered static HTML (the 'sea'), with isolated interactive components ('islands') that hydrate independently.
Benefits: Reduces JavaScript payload, eliminates unnecessary hydration of static content, improves performance on low-end devices, and maintains SEO benefits of server rendering.
Contrast with traditional SSR: Standard Next.js Pages Router hydrates the entire application at once, blocking interactivity until all JavaScript loads and executes.
Islands can be loaded based on triggers: viewport visibility, user interaction, idle time, or media queries.
Next.js App Router's React Server Components (RSC) provide a natural foundation for Islands Architecture. By default, all components are Server Components that render on the server and send zero JavaScript to the client. Only components marked with 'use client' become interactive islands that hydrate. This means you can build pages where 90% of the UI is static HTML, and only the truly interactive pieces (buttons, forms, carousels) become client components. The key insight is that Server Components can render Client Components, creating clear boundaries where hydration occurs.
For more sophisticated partial hydration scenarios, community libraries provide additional control. Libraries like next-lazy-hydrate allow you to defer component hydration based on triggers like viewport visibility, user interaction (hover, click), or idle time. These libraries work by skipping the initial hydration of components and loading their JavaScript only when needed. This can dramatically improve TTI (Time to Interactive) on pages with many interactive elements that don't need to be interactive immediately. The library react-hydration-on-demand provides similar functionality with a simple API.
For complete control, you can implement your own viewport-based hydration using the Intersection Observer API. This approach lets you detect when a component becomes visible and load its JavaScript only at that moment. Combined with React's lazy loading and Suspense, this creates a powerful pattern where off-screen interactive components don't block the initial page load. This is particularly valuable for long pages with interactive elements below the fold.
Immediate (client:load): Hydrates as soon as page loads. Use for critical UI above the fold.
Idle (client:idle): Hydrates after browser idle time. Use for non-critical enhancements.
Visible (client:visible): Hydrates when component enters viewport. Perfect for below-the-fold content.
Media query (client:media): Hydrates only when media condition matches. Great for mobile-only components.
Interaction (hover/click): Hydrates on first user interaction. Good for tooltips, dropdowns.
Next.js is evolving toward Partial Prerendering (PPR), which conceptually aligns with Islands Architecture but works differently. PPR prerenders a static shell at build time while leaving dynamic 'holes' that stream at request time. Islands Architecture traditionally loads static HTML first, then hydrates client-side. PPR combines both: static shell from CDN, dynamic content streams from server. In Next.js 15+, you can enable PPR experimentally to get a similar outcome: most of the page is static, interactive islands are dynamic and can access server-side data like cookies and headers.
Time to Interactive (TTI): Can improve by 50-80% by deferring non-critical hydration.
First Input Delay (FID): Reduces because main thread is free during initial page load.
JavaScript bundle size: Up to 90% reduction in initial JS for content-heavy pages.
Lighthouse scores: Islands architecture typically yields scores above 90 on content sites.