React Curriculum

Streaming SSR with Suspense & Selective Hydration

Hard100% Free~30 mins#react#ssr#streaming#suspense#selective-hydration#performance
Interview Answer (30-Second Summary)

React 18 Streaming SSR uses renderToPipeableStream and Suspense boundaries to break HTML generation into streams, flushing shells immediately while slow queries stream in later. Selective Hydration begins hydrating ready components before all HTML or scripts finish downloading.

Key Learning Objectives
✓

Explain how renderToPipeableStream flushes early HTML shells before slow database queries resolve.

✓

Structure Suspense boundaries to stream independent UI blocks concurrently without blocking the page.

✓

Explain how Selective Hydration hydrates ready components early and prioritizes user click interactions.

✓

Analyze the waterfall reduction achieved by streaming vs traditional blocking SSR.

The Interview Problem & Context

Explain how React 18 breaks the traditional SSR "waterfall bottleneck" using Streaming HTML and Selective Hydration.

1import React, { Suspense } from 'react';
2
3// Shell: Fast, synchronous, flushed immediately!
4export function NewsPage() {
5 return (
6 <div className="layout">
7 {/* 1. Flushed in first HTTP chunk: Immediate FCP! */}
8 <Header />
9 <Navigation />
10
11 {/* 2. Main content: Fast fetch */}
12 <Suspense fallback={<ArticleSkeleton />}>
13 <TopArticles />
14 </Suspense>
15
16 {/* 3. Slow comments: Does NOT block Header or Articles from rendering/hydrating! */}
17 <Suspense fallback={<CommentsSkeleton />}>
18 <SlowCommentsSection />
19 </Suspense>
20
21 <Footer />
22 </div>
23 );
24}
25
26// Server streaming entry point (Node.js)
27import { renderToPipeableStream } from 'react-dom/server';
28
29export function handleRequest(res: any) {
30 const { pipe } = renderToPipeableStream(<NewsPage />, {
31 bootstrapScripts: ['/main.js'],
32 onShellReady() {
33 // First chunk containing Header, Navigation, and fallbacks sent immediately!
34 res.setHeader('content-type', 'text/html');
35 pipe(res);
36 },
37 onError(err) {
38 console.error('Streaming error:', err);
39 },
40 });
41}
Deep Architectural Explanation

The Death of the SSR Waterfall

The 3 Bottlenecks of Legacy SSR:

  1. Fetch Bottleneck: The server cannot send ANY HTML until all backend queries finish.
  2. Download Bottleneck: The browser cannot hydrate until all JavaScript bundles download.
  3. Hydration Bottleneck: React cannot make any component interactive until every component hydrates.

How React 18 Streaming SSR Solves This:

  1. Streaming HTML via renderToPipeableStream:
    • React immediately renders the outer shell and wraps slow components in fallback skeletons.
    • The initial HTML is flushed over the HTTP response in milliseconds.
    • As slow components resolve on the server, React streams inline script tags that replace the skeleton with actual HTML in-place!
  2. Selective Hydration:
    • Components wrapped in Suspense do not block other components from hydrating.
    • If TopArticles finishes downloading its JS, React hydrates it immediately—even while SlowCommentsSection is still loading!
  3. Interaction-Driven Prioritization:
    • If the user clicks on Comments while React is busy hydrating TopArticles, React pauses hydrating articles and immediately hydrates the clicked comments section to handle the user interaction without lag!
Common Interview Traps & Pitfalls
✕

Wrapping the entire application in a single root Suspense boundary, defeating granular streaming.

✕

Using legacy renderToString which blocks streaming and requires waiting for all promises.

✕

Assuming streamed HTML requires client-side JavaScript execution to display.

Senior Interviewer Follow-Up Probes
?

How does HTTP chunked transfer encoding (Transfer-Encoding: chunked) enable streaming responses?

?

How does Selective Hydration interact with Concurrent Mode scheduler priorities?

?

What is the difference between onShellReady and onAllReady in renderToPipeableStream?

Frequently Asked Interview Questions
What is Streaming SSR in React 18?

A rendering architecture where the server sends the HTML page in multiple streaming chunks as data becomes ready, rather than waiting for the entire page to finish before sending the first byte.

A feature of React 18 that allows individual subtrees wrapped in Suspense boundaries to hydrate independently as their code loads, rather than requiring the entire page to hydrate in one monolithic pass.

If a user clicks on an unhydrated component, React intercepts the native event, prioritizes hydrating that specific subtree ahead of others, and replays the user interaction seamlessly.

The Node.js server rendering API in React 18+ that outputs a readable Node stream of HTML, supporting progressive streaming, Suspense fallbacks, and shell readiness callbacks.

onShellReady fires as soon as the initial UI shell outside Suspense boundaries is ready to stream to browsers. onAllReady waits until all Suspense boundaries complete, useful for web crawlers/SEO bots.

Yes. The server streams inline scripts that swap skeleton placeholders with real HTML, meaning users see complete rendered HTML even before full client hydration bundles run.