ssr 页面闪屏的根本原因是 serverstylesheet 使用错误:未新建实例、未 collectstyles、未插入 getstyletags()、未 seal,导致服务端未输出样式;同时客户端与服务端 theme、props、版本或环境不一致,造成 class 名不匹配,引发 fouc。

必须在服务端渲染阶段正确注入样式标签,否则客户端 hydration 时必然 FOUC——ServerStyleSheet 用错一次,首屏就闪。
为什么 SSR 后页面还是闪:ServerStyleSheet 没用对
Next.js 或 Express + React SSR 场景下,ServerStyleSheet 被复用、未 seal、或未在 HTML 字符串中插入 getStyleTags(),都会导致服务端没吐出样式,浏览器只能等 JS 加载完才补样式。
- 每次渲染必须新建实例:
const sheet = new ServerStyleSheet(),不能跨请求复用 - 必须调用
sheet.collectStyles()包裹整个 App,不是单个组件 - 必须把
sheet.getStyleTags()插入返回的 HTML 字符串里(通常在中) - 必须在 finally 块调用
sheet.seal(),否则内存泄漏且后续调用报错Can't collect styles once you've consumed...
Next.js 项目里怎么配才不闪
Next.js 13+ App Router 默认不支持 styled-components 的传统 SSR,需手动接管 renderToHTML 流程;Pages Router 则更直接,但仍有陷阱。
- Pages Router:在
pages/_document.tsx的getInitialProps中初始化ServerStyleSheet,将styles注入props.styles,再在render()中用{props.styles}输出 - App Router:无法直接用
ServerStyleSheet,必须改用@emotion/server或迁移到 CSS Modules / Tailwind;若坚持用 styled-components,需配合styled-components-babel-plugin提取静态样式,并在generateStaticParams阶段预构建 - 别在组件内调用
useEffect注入样式——SSR 阶段不执行,必然闪
客户端 hydration 时样式错乱的典型表现
服务端样式已注入,但页面加载后仍短暂出现无样式状态,常见于以下情况:
- 客户端和服务端的
theme或props不一致(比如 localStorage 主题未同步到初始 HTML),导致生成的 class 名不同,样式不匹配 - 用了动态插值(如
color: ${props => props.theme.primary})但服务端未传入完整 theme 对象 -
styled-components版本 mismatch:服务端用 v6,客户端打包进 v5,class 前缀不一致,样式被忽略 - 未禁用 dev 模式:生产环境必须设
process.env.NODE_ENV = 'production',否则服务端不会 hash class 名,客户端可能找不到对应规则
最易被忽略的是 theme 同步和版本一致性——哪怕 class 名只差一个字符,浏览器就当它不存在,FOUC 就不可逆。服务端吐出的 HTML 必须和客户端 hydrate 时看到的完全一致,包括所有插值结果和哈希前缀。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











