SSR 水合问题 为什么需要 SSR在正式回答水合之前先理解一个问题为什么要有 SSR传统的CSR客户端渲染流程是浏览器下载一个空壳 HTML然后 JS 下载执行后才渲染出内容。这导致两个核心问题首屏白屏时间长— 用户盯着空白页面等 JS 下载执行SEO 不友好— 搜索引擎爬虫抓到的也是空壳 HTML没法索引内容SSR服务端渲染就是来解决这两个问题的——​在服务端就把完整的 HTML 生成好​浏览器拿到的直接就是有内容的页面。先看一张 SSR 和 CSR 的对比图SSR 的核心一次请求三阶段一个 SSR 请求从用户浏览器点击到页面可交互经历了三个阶段。阶段一服务端渲染用户请求一个页面比如/productsNode.js 服务端Vite/Webpack 帮我们做的​同步获取数据​调用 API 或查数据库把数据传入组件​渲染成 HTML 字符串​比如 React 的renderToString()把数据​序列化后嵌入 HTML​常见做法是塞进scriptwindow.__INITIAL_STATE__.../script返回完整 HTML阶段二浏览器展示浏览器收到 HTML 后直接开始渲染。用户​立刻就能看到页面内容​不需要等 JS 下载完。这就是 SSR 最大的优势——​首次内容绘制FCP极快​。阶段三水合Hydration浏览器同时下载 JS bundle下载完成后开始 ​**「水合」**​重建组件树重新跑一遍组件代码把服务端生成的 DOM 结构跟组件树做「对账」reconciliation对账通过后​绑定事件监听器​页面才变得可交互水合问题详解什么是水合这个名字取自化学里的水合物概念——​把干的服务端 HTML加水JS 事件绑定让它重新活过来​。水合的核心流程步骤做了什么服务端renderToString(Component)→ 产出 HTML 字符串浏览器收到立即展示 HTML用户看到内容了浏览器下载 JS解析执行组件代码重建虚拟 DOM水合开始虚拟 DOM 和已有 DOM 做对账reconciliation对账通过保留 DOM只绑定事件监听器对账失败丢弃服务端 DOM重新渲染 →水合失败水合失败的典型案例看图。假设一个电商页面上显示商品数量10这是服务端渲染时查数据库得到的。但 JS bundle 下载 解析完成时后台已经新增了 2 件商品客户端组件重新跑代码拿到的是 12。于是​服务端 DOM 文本节点​商品数量: 10​客户端虚拟 DOM 文本​商品数量: 12React 对账发现10 ! 12→ 它认为服务端的 DOM 是错的 →用客户端的覆盖它→ 闪屏。更糟的情况如果组件的结构都不一样了比如条件渲染框架会​直接卸载整个子树重新挂载​SSR 的首屏加速效果全部白费。最常见的 4 类触发原因时间敏感数据—new Date().toLocaleString()、Math.random()服务端和客户端运行时不同结果浏览器 API 依赖— 读取window.innerWidth判断是移动端还是桌面端服务端没有window数据在请求间隙发生变化— 上面那个商品数量的例子第三方脚本修改了 DOM— 广告脚本、分析脚本在 JS bundle 加载前已经改了 HTML三种主流解决方案方案一消除不同源这是最彻底的解法——客户端水合时不要重新请求数据直接用服务端序列化过来的那一份!-- 服务端在 HTML 末尾嵌入 -- script window.__INITIAL_STATE__ { products: 10, // 跟渲染 HTML 时用同一个值 user: { name: 用户 } } /script客户端水合时读取window.__INITIAL_STATE__不用重新 fetch保证两端数据一致。方案二抑制水合警告框架常用做法对于注定不同的动态内容比如当前在线人数这种实时数据主动告诉框架别管了​React​:suppressHydrationWarning{true}​Vue/Nuxt​:ClientOnly包裹服务端不渲染这部分​Next.js​:use client 动态导入禁用 SSR方案三流式 SSR 选择性水合React 18 引入的架构级改进Suspense 包裹每个区域独立 SSRHTML 流式返回不必等全部数据​选择性水合​——用户点击了某个按钮React 优先水合那个交互区域而不是从头到尾水合全部​**Server ComponentsRSC**​——部分组件永远只在服务端运行不发送 JS 到客户端从源头消除水合问题总结CSR客户端渲染 请求 - 返回空壳 - 下载 JS - 渲染 - 可交互 ❌ 白屏期长 SSR服务端渲染 请求 - 服务端渲染 HTML - 返回完整 HTML - 立即可见 后台下载 JS - 水合 - 可交互 ✅ 首屏快 水合问题 服务端 HTML 和客户端虚拟 DOM 不一致 - 闪屏 / 重渲染 / SSR 白费 ⚠️ 需要处理SSR 不是银弹——它解决了首屏速度和 SEO 问题但引入了服务端开销和水合复杂度。