·更新于 2026年10月25日· 9 次浏览 NuxtVue3SSRHydrationBUG解决工程实践
Nuxt 3 首页偶发 Hydration Mismatch:我把问候时间和随机标签挪到客户端
首页偶发 Hydration mismatch,最后发现是服务端和浏览器对时间、随机标签算出了不同结果。我把这类不稳定内容改成客户端补丁,首屏只保留稳定占位。

作者
ZHOUYI
前几天首页偶尔在控制台报 Hydration mismatch。复现后发现,问题不在接口,而在首屏那句“早上好/下午好”和一个随机标签。服务端渲染时算了一次时间,浏览器 hydrate 时又按本地时间算了一次,差几分钟就撞上不一致。
为什么动态时间和随机数容易踩坑
Nuxt 3 的 SSR 会先在 Node 里生成 HTML,浏览器再接管。像当前时间、随机数、窗口宽度、登录态这类信息,服务端和客户端天然可能不同。如果模板直接依赖它们,Vue 对比新旧 DOM 时就会报警。这类错不一定白屏,但会让组件状态变怪,也会掩盖真正的渲染问题。
我的处理:首屏只给稳定占位,客户端再补丁
- 把问候语和随机标签从 SSR 渲染逻辑里拆出来,不再参与首屏 HTML 的关键内容。
- 模板先渲染固定文案或骨架,保证服务端输出的 HTML 是稳定可复现的。
- 在 onMounted 里根据浏览器本地时间和随机源生成真实内容,完成一次客户端补丁。
- 如果内容影响 SEO,只把稳定正文交给 SSR,动态装饰、广告位、个性化标签放到客户端。
vue
<script setup>
const text = ref('')
onMounted(() => {
const h = new Date().getHours()
const tag = ['工程', '踩坑', '随笔'][Math.floor(Math.random() * 3)]
text.value = `${h < 12 ? '早' : h < 18 ? '午' : '晚'}·${tag}`
})
</script>
<template><p>{{ text || '你好' }}</p></template>我踩过的坑是:一开始只想把报错压掉,就在客户端强制覆盖整块 DOM。后来发现更稳的做法是区分内容等级:正文、标题、结构化数据交给 SSR,问候、随机推荐、广告标识这类装饰性内容交给客户端。这样既保留 SEO,又避免首屏 HTML 被不稳定值污染。
小结
这类问题本质是“服务端和浏览器看到的上下文不一致”。凡是两边可能算出不同结果的内容,要么提前固化,要么延迟到客户端补丁。首页这种高频入口,宁可少一点即时动态,也要先保证 hydration 稳定。