css-in-js 天然无法生成纯净标记文件,因其依赖运行时动态注入样式,构建期无法产出含完整样式的独立 html;必须放弃 css-in-js,改用纯 css、styled-jsx 或工具内联关键 css 才能实现。

HTML 与 CSS-in-JS 在构建期无法共同生成“纯净标记文件”——这是根本性冲突,不是配置问题。
为什么 CSS-in-JS 天然不产出静态 HTML 文件
CSS-in-JS(如 styled-components、Emotion)的核心机制是在运行时动态注入 <style></style> 标签或内联 style 属性。即使启用 SSR(服务端渲染),它输出的 HTML 仍包含运行时依赖的 class 名(如 sc-bdVaJa abc123),且样式规则本身通常不内联进 HTML,而是由 JS 脚本在客户端执行后才生效。
- 构建产物中没有独立、可直接打开的 .html 文件含完整样式 —— 它依赖 JS 加载和执行
-
document.createElement、insertRule、CSSOM 操作都是浏览器环境行为,Node.js 构建阶段无法真实模拟 - 所谓“静态导出”(如 Next.js 的
output: 'export')会 fallback 到 CSS-in-JS 的 SSR 快照,但缺失 JS 时样式丢失,不算“纯净标记”
想得到真正纯净的 HTML+CSS 文件?必须放弃 CSS-in-JS
“纯净标记文件”指:单个 .html 文件,打开即渲染正确,无 JS 依赖,所有样式通过 <style></style> 或内联 style= 内置,无外部请求。
- 用纯 CSS(或 PostCSS + Tailwind)配合静态生成器(如 Eleventy、Hugo、Vite 的
build.rollupOptions.output.manualChunks配合inline CSS插件) - 若坚持用 React 生态,选
styled-jsx并开启cssMode: 'string'(Next.js 支持),它能把组件级样式提取为字符串,在构建时写入 HTML 的<style></style> - 手动提取:用
critters或lightningcss工具将关键 CSS 内联到 HTML 的,再移除所有 JS 引用 —— 但前提是原始样式本身不能依赖 JS 计算(如 theme 依赖 context)
常见误判:“构建后有 .html 文件” ≠ 纯净标记文件
很多工具(如 Gatsby、Next.js)构建后确实输出 .html,但它们常混杂以下内容,导致无法脱离 JS 运行:
<div class="sc-aXZVg"> —— class 名哈希由 JS 运行时生成,静态 HTML 中该 class 对应的样式并不存在 <li> <code><script id="__NEXT_DATA__" type="application/json"></script>—— 数据驱动渲染,删掉就空白- 空的
<style data-styled=""></style>—— 实际规则在 JS bundle 里,构建期未提取 - 使用
useEffect或useState控制样式逻辑 —— 这类行为无法在构建期固化为静态标记
真正做静态站点(如文档页、营销页),别让 CSS-in-JS 进构建流水线;需要交互时再加载 JS。混淆“构建产物存在 HTML”和“HTML 自包含可运行”,是多数人卡住的关键点。











