增量式水合同构架构通过SSR输出完整HTML、客户端仅对视口内关键区域选择性水合,结合React 18并发能力、use client标记、Suspense懒加载及JS体积优化,显著提升TTI。

设计支持“增量式水合”的同构架构,核心是让页面在服务端渲染(SSR)输出完整 HTML 的同时,客户端只对用户真正需要、且处于视口或即将交互的关键区域进行水合,而非等待整页 JS 加载并同步激活。这直接压缩了从“内容可见”到“可点击/可输入”的时间差,显著优化 TTI(Time to Interactive)。
确保服务端与客户端渲染结构严格一致
增量水合依赖 React 18 的并发能力,但前提是服务端生成的 HTML 和客户端首次 render 的虚拟 DOM 树完全匹配。任何 mismatch 都会触发降级全量水合或警告,破坏增量逻辑。
- 避免在组件中直接使用 window、document 等浏览器专属 API —— SSR 时它们不存在,会导致服务端与客户端输出不一致
- 异步数据需通过服务端预取(如 getServerSideProps 或 RSC 的 server actions)注入初始 props,而不是在 useEffect 中客户端获取
- 慎用依赖 DOM 尺寸或位置的逻辑(如 getBoundingClientRect),这类代码应包裹在 useEffect 或 useLayoutEffect 中,确保仅在客户端执行
按交互优先级划分水合边界
不是所有组件都需要立即水合。把首屏核心操作路径(如搜索框、商品卡片的“加入购物车”按钮、文章页的“点赞”)标记为高优先级;页脚、广告位、评论区等延迟水合甚至静态保留。
- React 18 提供 client-only 组件标记方式:用 \"use client\" 指令显式声明需水合的模块,未声明的组件默认在服务端完成渲染,不下发 JS
- 结合 Suspense 和 React.lazy 实现动态水合时机控制,例如对非首屏模块设置 timeoutMs 或基于滚动懒水合
- 第三方 SDK(如统计埋点、客服弹窗)尽量通过事件委托或运行时注入,避免随主包一起水合
精简水合所需 JS 体积与执行负载
再聪明的增量策略也受限于 JS 下载、解析和执行耗时。TTI 延迟常源于主线程被大体积或高复杂度 JS 占满。
- 启用 Webpack / Vite 的 code splitting,确保每个可水合区块对应独立 chunk,按需加载
- 将非关键业务逻辑(如动画库、富文本编辑器)移出首屏水合链路,改用 onInteraction 触发加载
- 对大型组件树启用 React.memo + useCallback,减少水合阶段不必要的 reconciler 计算
- 监控主线程任务耗时,用 Chrome DevTools 的 Performance 面板识别长任务(>50ms),拆解或移交至 Web Worker
利用框架原生能力实现渐进接管
现代框架已内置对增量水合的支持,无需从零封装。关键是理解机制并正确启用。
- React 18 使用 hydrateRoot 替代旧版 hydrate,自动启用并发渲染与选择性水合
- Vue 3.4+ 支持 defineAsyncComponent 的 ssr: false 选项,明确跳过服务端渲染该组件,由客户端接管
- Next.js 14+ App Router 默认启用 RSC + partial hydration,关键交互组件加 \"use client\" 即可触发增量水合
- Qwik 则更进一步:默认零水合,只有绑定事件的元素才加载对应 JS,适合 M 站类极简触点场景

















