样式闪烁源于服务端与客户端css-in-js的class名生成不一致,核心在于cache实例、哈希算法、插件配置及标签属性必须完全对齐,且需清除缓存残留以确保构建一致性。

样式闪烁不是 CSS-in-JS 本身的问题,而是服务端与客户端 class 名生成逻辑不一致导致水合失败。只要两端哈希算法、插件配置、缓存实例、<style></style> 标签属性完全对齐,就能彻底避免。
确保服务端与客户端 cache 实例完全一致
Emotion、@ant-design/cssinjs 等库依赖 cache 实例生成 class 名。服务端用一个 cache,客户端又新建一个,class 名必然不同,水合时样式就“掉”了。
- Next.js 中必须复用同一个
createCache()实例,不能在每次请求或组件中重新创建 - cache 的
key必须固定(如'css'),且stylisPlugins数组内容和顺序要完全相同 - 服务端渲染后调用
extractStyle(cache),客户端 hydration 前必须用同一 cache 初始化StyleProvider - 若用
useInsertionEffect注入样式,它在 SSR 中不执行——必须改用useEffect+typeof window !== 'undefined'客户端检测
所有
SSR 提取工具(如 @emotion/server 或 Next.js 内部机制)靠 data-emotion 或 data-styled 识别哪些 <style></style> 是 CSS-in-JS 生成的,才能内联到 HTML 中。漏掉这个属性,样式就只在客户端注入,首屏必然闪。
- Emotion:确保
<style></style>含data-emotion="css"和对应data-s值 - Styled-components:启用
StyleSheetManager并设disableVendorPrefixes: true,否则服务端加的前缀可能和客户端不匹配 - Ant Design:必须用
<styleprovider ssrinline></styleprovider>包裹,否则extractStyle()拿不到完整样式
避免在服务端组件里触发客户端专属逻辑
Next.js App Router 下,服务端组件(Server Component)里调用 useTheme、读 window.matchMedia 或 localStorage,会导致服务端渲染出默认主题 HTML,客户端再切主题,视觉上就是“闪一下”。
- 主题切换必须由
next-themes的ThemeProvider统一管理,并设theme={'system'}或预设值 -
tailwind.config.ts中darkMode必须为'selector',且初始 HTML 的上要有data-theme="dark" - 绝对不要在 Server Component 里 import 或调用任何依赖
window的 Hook 或函数
最容易被忽略的是缓存残留:PostCSS、Emotion、Vite 的 CSS 缓存不会自动失效,.next/cache/postcss 或 node_modules/.vite/deps 里旧的 class 名可能还在生效。改完配置后,务必手动清空再构建。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











