Hydration Mismatch

SSR 经常出现的问题就是 hydration mismatches

Hydration mismatch

要了解什么是 Hydration,请参考 What is hydration? 指南

hydration mismatch 指的是 HTML 在 Node.js 和浏览器中渲染的内容不同

Hydration mismatches 会导致性能下降和错误,因此应该避免

Example

假设我们渲染当前日期的毫秒数:

<span>{new Date().getMilliseconds()}</span>

这会导致 hydration mismatch,因为在服务端渲染的毫秒数(例如 <span>123</span>)跟浏览器端渲染的毫秒数(例如 <span>167</span>)不匹配

为了防止 hydration mismatch,我们应该确保渲染相同的毫秒值,我们可以通过 onBeforeRender() 做到这一点

export { onBeforeRender };

async function onBeforeRender() {
  const milliseconds = new Date().getMilliseconds();
  return {
    pageContext: {
      milliseconds,
    },
  };
}
<span>{pageContext.milliseconds}</span>

这里发生的是:pageContext.milliseconds 会被设置一次,相同的毫秒值将在 Node.js 中渲染到 HTML 中,并在浏览器端 hydrate。(我们使用export passToClient = ['milliseconds']pageContext.milliseconds 传递给浏览器端)

常见原因 & 解决方案

常见原因:

  • 渲染内容实际上不同。确保你的组件在 Node.js 和浏览器中渲染相同的内容
  • 浏览器缓存: 在开发阶段,请禁用浏览器缓存,以确保浏览器不会加载缓存和过时的 JavaScript
  • 代理: 如果你使用代理,请确保它不会使用有问题的 HTML 转化器。例如,如果你使用 Cloudflare,则必须禁用 Cloudflare 的 HTML 自动压缩器

React 中:

  • 老 React 版本 在拼接文本段时存在错误,导致 Warning: Text content did not match.。确保使用最新的 React 版本

阻止 Hydration Mismatch

在某些情况下,hydration mismatches 不可避免,阻止 hydration mismatch 警告: