对应源码:
packages/react-dom/src/server/,packages/react-server-dom-webpack/
1. SSR 的两种模式
传统 SSR(React 16-17):
renderToString(element) → 返回完整 HTML 字符串
→ 客户端 hydrate(重新执行所有组件代码)
问题:必须等所有数据准备好才能返回 HTML
流式 SSR(React 18+):
renderToPipeableStream(element)
→ 流式返回 HTML chunks
→ [Suspense](https://react.dev/reference/react/Suspense) 边界允许部分内容先返回
→ 数据就绪后流式补充剩余内容React 18 引入了全新的 SSR 架构,支持流式输出和选择性水合。
2. 流式 SSR 的工作方式
Server:
<html>
<head>...</head> ← 立即流式返回
<body>
<header>Nav</header> ← 立即返回(无Suspense包裹)
<Suspense fallback={<Spinner/>}>
<Comments /> ← 需要等数据
</Suspense>
</body>
Timeline:
T=0: 流式返回 <html><head><body><header>Nav</header>
T=0: 流式返回 <div hidden id="B:1"><!--$--> ← Suspense 占位符
T=0: 流式返回 <div class="spinner"></div> ← fallback UI
T=0: 流式返回 <!--/$--></div>
T=0: 流式返回 <script>...</script> ← hydration JS
T=2s: 数据就绪
T=2s: 流式返回 <div hidden id="B:1">
T=2s: <template>...Comments HTML...</template>
T=2s: <script>$RC("B:1")</script> ← 替换 fallback 为真实内容3. Hydration
Hydration 是将服务端返回的 HTML 与客户端 React 状态连接的过程:
SSR 返回的 HTML:
<div data-reactroot>
<span>Hello</span>
<button>Click</button>
</div>
客户端 hydrate:
→ React 遍历组件树(与 render 类似)
→ 不创建 DOM(DOM 已存在)
→ 而是 attach 事件监听器
→ 验证 server HTML 和 client render 是否一致
→ 如果不一致 → warning(开发模式)
React 18 [Selective Hydration](https://www.patterns.dev/react/react-selective-hydration/):
→ 用户点击某个区域 → 优先 hydrate 那个区域
→ 不需要等待整页 hydrate 完成