RFSOC学习记录(五)带通采样定理

莱逞诎驮一、什么是 Hydration

在 SSR 项目中,页面渲染实际上分为两个阶段:

服务器渲染(SSR):生成 HTML

客户端接管(Hydration):绑定事件、恢复状态

Hydration 的定义可以概括为:

在不重新创建 DOM 的前提下,让客户端 JS 接管服务器生成的 HTML,使得一块干燥的海绵有了水分的注入变得能有 "交互性"(捏一捏挤出水)

1.1 为什么需要 Hydration

如果没有 Hydration,客户端接管一个有 "间谍" 的 HTML,只能:

删除已有 DOM

重新执行一次 CSR 渲染

这会导致:

首屏闪烁

性能浪费

用户体验下降

因此现代 SSR 框架都会尝试 复用已有 DOM,只在必要时补充缺失的属性或绑定事件,这就是 Hydration 的意义。

二、Hydration 过程中做了什么

以 Vue / React 为例,Hydration 主要做三件事:

遍历已有 DOM

生成虚拟 DOM

对比并绑定事件

核心前提只有一个:

客户端生成的虚拟 DOM 必须与服务器生成的 HTML 结构完全一致

否则就会出现 mismatch。

三、什么是 Hydration Mismatch

Hydration mismatch 指的是:

客户端首次渲染得到的虚拟 DOM,与服务器返回的 HTML 不一致

此时框架会:

给出 warning(开发环境)

丢弃已有 DOM

重新执行一次完整的客户端渲染

3.1 常见警告示例(Vue)

Hydration completed but contains mismatches.

或者:

Text content does not match server-rendered HTML.

四、为什么会产生 Mismatch(核心原因)

本质原因(只有一个)

SSR 与 CSR 执行环境不同,但代码写成了"依赖运行时环境"的形式

4.1 使用了浏览器专属对象

const width = window.innerWidth

服务端:window 不存在

客户端:存在

导致渲染结果不一致。

4.2 使用了不稳定的值

1?? 时间相关

{{ Date.now() }}

SSR:构建时间

CSR:当前时间

结果必然不一致。

2?? 随机数

Math.random()

3?? 非确定性排序

list.sort(() => Math.random() - 0.5)

4.3 条件渲染依赖客户端状态

Mobile

const isMobile = window.innerWidth < 768

SSR 无法得知客户端宽度。

4.4 服务端与客户端数据不一致

// 服务端

const data = await fetch('/api/data')

// 客户端

const data = await fetch('/api/data')

如果数据在两次请求之间发生变化,就会 mismatch。

4.5 HTML 结构不合法

content

浏览器会自动修正 DOM 结构,导致:

SSR 输出 ≠ 浏览器实际 DOM

五、Hydration Mismatch 的"隐性后果"

即使页面"看起来正常",仍然可能存在问题:

页面被强制重新渲染

首屏性能指标下降(LCP / FCP)

事件绑定延迟

某些节点丢失状态

这也是为什么 不应该忽视 warning。

六、如何系统性避免 Hydration Mismatch

6.1 核心原则(非常重要)

首屏渲染必须是"纯函数"

相同输入

相同输出

不依赖运行环境

6.2 延迟到客户端执行(onMounted)

const width = ref(0)

onMounted(() => {

width.value = window.innerWidth

})

6.3 使用客户端专用组件

Nuxt 示例

6.4 使用 process.client / import.meta.client

if (import.meta.client) {

// 只在客户端执行

}

6.5 保证数据只在一侧生成

服务端生成 → 客户端复用

useAsyncData('list', fetchList)

6.6 对不可避免的差异进行兜底

{{ clientOnlyValue }}

6.7 骨架屏、占位符结合判断也是不错的想法哟~

七、排查 Hydration Mismatch 的思路

关注首个 warning

锁定报错节点

排查是否使用了不稳定值

检查条件渲染

确认数据是否重复请求

查看 HTML 结构是否合法

八、错误示例与修复

错误示例

{{ new Date().toLocaleString() }}

修复方案

{{ time }}

九、框架层面的设计取舍

需要明确一点:

Hydration mismatch 并不是框架 bug,而是开发者违反了 SSR 的约束条件

SSR 框架已经尽可能"宽容",但它无法猜测开发者的真实意图,so you 要去迎合它。

十、SO

Hydration mismatch 的核心结论只有三点:

SSR 与 CSR 必须输出一致的 HTML

首屏渲染不能依赖运行时环境

不确定性逻辑必须延迟到客户端

如果你把 SSR 页面当作:

一个"可复现的纯函数渲染结果"

那么 Hydration mismatch 将大幅减少。

Finally

在实际项目中,我的建议是:

能 SSG 的页面,尽量 SSG

能 CSR 的交互,尽量 CSR

SSR 页面只承载"稳定首屏内容"