css-in-js 服务端渲染需分离样式收集与注入:服务端用 stylesheetmanager 等收集规则并内联至 html head,客户端 hydrate 复用;须共用样式引擎实例、避免动态创建、禁止 ssr 阶段副作用触发样式生成。

因为 CSS-in-JS 默认在客户端运行时动态插入 <style></style> 标签,而 SSR 要求 HTML 在返回前就包含全部样式 —— 否则页面首屏会闪白、无样式,或客户端水合(hydration)时样式错乱。
服务端无法访问 document.styleSheets
CSS-in-JS 库(如 styled-components、emotion)默认依赖浏览器 DOM API,比如 document.head.appendChild 或 document.styleSheets。Node.js 环境没有 document,直接调用会报错:ReferenceError: document is not defined。
解决方式不是“绕过”,而是切换渲染路径:
- 服务端用「样式收集器」(如
StyleSheetManager、ServerStyleSheet、StyletronServer)捕获所有生成的规则 - 客户端用「样式注入器」(如
hydrate或useStyletron)接管并复用这些规则 - 关键点:服务端不写
<style></style>到 DOM,只收集;客户端不重复生成,只 hydrate
客户端水合时样式 ID 不匹配
很多 CSS-in-JS 库靠哈希或计数器生成 class 名(如 sc-bdVaJa),但服务端和客户端若使用不同实例或未同步状态,class 名会不一致,导致样式丢失。
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
典型现象是:服务端渲染出 <div class="sc-abc123">,客户端 hydrate 后变成 <code><div class="sc-def456">,样式表里找不到后者。
<p>必须确保:</p>
<ul>
<li>服务端和客户端共用同一套样式引擎实例(如 <code>createInstance + 传递 context)
<style></style> 标签内联进 HTML )StyleSheet)Next.js 等框架中 getServerSideProps 无法直接调用 styled 组件
在 getServerSideProps 里调用 styled.div 会失败,不是因为函数不能执行,而是它返回的组件在服务端无法被 renderToString 正确处理 —— 它依赖 React 的 context 和运行时 hook,而 SSR 渲染阶段尚未建立完整 React 运行环境。
正确做法是:
- 样式定义放在组件外部(即不依赖 props 动态生成的静态
styled) - 动态样式逻辑移到组件内,用
cssprop 或className+ 主题对象控制 - 若必须条件式生成样式,改用编译时方案(如
Compiled或Linaria),它们在构建期就把样式转成静态 CSS,完全规避运行时问题
最易被忽略的一点:即使你用了 ServerStyleSheet,如果组件在服务端渲染前触发了副作用(比如 useEffect 里调用了 styled 创建器),依然会漏收样式 —— SSR 必须保证所有样式定义发生在 renderToString 执行期间,且无异步延迟。










