服务端渲染出的 html 带 light 类,客户端读本地存储后改成 dark,控制台报 hydration failed,肉眼能看到闪一下。日志里能对上时间点,这种反而好排。

服务端拿不到 localStorage,只能输出默认主题,客户端首帧又立刻改成用户选择,两边标记不一致。水合阶段 React 直接丢弃服务端结构重渲染。这一点先确认清楚,后面就不用反复试。

// 服务端读取 cookie 后输出
<html data-theme={cookieTheme ?? 'light'}>

// 客户端挂载前同步补齐
<script dangerouslySetInnerHTML={{__html: themeScript}} />

围绕「SSR 主题闪烁」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。

日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。权限不要一口气开到最大,先加到够用再往上试,范围小才好收。

处理上按这个顺序:把主题写进 cookie 服务端读取后直接输出对应类名;或用内联脚本在 hydrate 前设好属性 并给 html 加 suppressHydrationWarning;清缓存后刷新 看控制台是否还有 hydration 警告。

结果对不对很好判断,首屏直接是用户选的暗色,控制台没有 hydration 警告。

作者 9823189