Nuxt3中使用Day.js或dayjs-nuxt模块,加载中文语言配置后构建项目出现Hydration completed but contains mismatches.
具体现象:页面刷新时先是英文一闪而过然后才会正确显示中文,例如页面刷新后显示"a month ago"然后瞬间变会"1 个月前",控制台报错BGBimpvY.js:14 Hydration completed but contains mismatches.
这个问题是由于服务端渲染(SSR)和客户端水合不匹配导致的。服务端使用英文渲染,客户端加载后又立即切换成中文,造成水合错误。
假设我们直接引入Day.js或者通过dayjs-nuxt模块使用Day.js
方式一、直接引入Day.js
npm install dayjs
// plugins/dayjs.ts
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import 'dayjs/locale/zh-cn'
export default defineNuxtPlugin(() => {
dayjs.extend(relativeTime)
dayjs.locale('zh-cn')
return {
provide: {
dayjs
}
}
})
<template>
<span>{{ $dayjs('2025-09-04T19:00:00.000+00:00').fromNow() }}</span>
</template>
方式二、引入dayjs-nuxt模块
npx nuxi@latest module add dayjs
// nuxt.config.ts
modules: ['dayjs-nuxt']
dayjs: {
locales: ['zh-cn'], // 加载中文语言包
defaultLocale: 'zh-cn' // 设置默认语言
// 默认会引入 relativeTime 和 utc 插件
},
<template>
<span>{{ $dayjs('2025-09-04T19:00:00.000+00:00').fromNow() }}</span>
</template>
以上的配置在开发环境中似乎不会什么问题,但是通过npm run build构建打包部署到生产环境或者通过npm run preivew预览便会出现文章开头的情况。
通过查看dayjs-nuxt模块仓库issues发现有不少开发者已经提到了这个问题。似乎是由于import 'dayjs/locale/zh-cn'
这样的加载方式(dayjs 加载语言包通常是通过一种“副作用导入”(side-effect import)的方式)并没有将文件内容赋值给一个变量,导致打包工具进行摇树优化(Tree-Shaking)的时候以为只是导入了这个文件,但没有从它里面导出任何变量来使用,所以这个导入是多余的,我可以把它‘摇掉’(删除掉)以减小最终打包的体积。
现在对以上两种引入方式做出调整
针对直接引入Day.js的方式,需要显式导入并赋值给变量,避免在构建时被优化掉,修改配置如下:
// plugins/dayjs.ts
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
- import 'dayjs/locale/zh-cn'
+ // 显式导入并赋值给变量,避免在构建时被优化掉
+ import zhCn from 'dayjs/locale/zh-cn'
export default defineNuxtPlugin(() => {
dayjs.extend(relativeTime)
- dayjs.locale('zh-cn')
+ // 显式设置语言包
+ dayjs.locale('zh-cn', zhCn)
return {
provide: {
dayjs
}
}
})
针对引入dayjs-nuxt模块的方式,需手动引入和配置中文语言,添加插件如下:
// https://github.com/fumeapp/dayjs/issues/44#issuecomment-3052536121
// plugins/dayjs-locale.ts
export default defineNuxtPlugin(({ hook }) => {
// 语言包配置
const locales = {
// 动态导入,按需加载
'zh-cn': () => import('dayjs/locale/zh-cn'),
}
const { $dayjs } = useNuxtApp()
// 监听 app:created 事件,在应用创建时执行(应用创建时的钩子)
hook('app:created', async () => {
// 设置 Day.js 的语言环境
const currentLocale = 'zh-cn' // 或从其他地方获取当前语言
// 异步加载语言包
const localeModule = await locales[currentLocale]()
$dayjs.locale(currentLocale, localeModule.default)
})
})
参考文章:https://github.com/fumeapp/dayjs/issues/44
参考文章:Claude-4、Gemini-2.5