Node.js SSR 引入 CSS 的核心是确保 CSS 内容注入 HTML 字符串,关键在打包配置与环境匹配:Webpack 服务端禁用 MiniCssExtractPlugin,改用 fs.readFileSync 读取;Vite 需 vite-plugin-css-injected-by-js 插件显式收集;React/Vue 必须同步边渲染边收集样式,覆盖所有边界组件。

开发环境下 Node.js SSR 引入 CSS,核心不是“能不能 import”,而是“import 后 CSS 内容是否真进了 HTML 字符串”——绝大多数问题出在打包器配置和执行环境错配,而非代码写法本身。
Webpack 服务端构建时 document is not defined 怎么办
这个错误本质是 MiniCssExtractPlugin 在 Node 环境下试图操作浏览器 DOM。它只该用在客户端构建(target: 'web'),服务端构建必须禁用。
- 在 Webpack 的服务端配置(
target: 'node')中,彻底移除MiniCssExtractPlugin.loader,别尝试“兼容性降级” - 改用
css-loader,并确保options.modules: false(普通 CSS)或exportOnlyLocals: true(仅导出类名,不生成样式字符串) - 如果需要把 CSS 内容拼进 HTML,别依赖
import返回值——它在服务端是空对象;改用fs.readFileSync('./dist/main.css', 'utf8')手动读取编译后文件
Vite SSR 中 import './style.css' 没反应
Vite 默认不收集服务端已加载的 CSS 内容,import 只触发模块加载,不触发样式提取。这不是 bug,是设计使然。
- 必须安装
vite-plugin-css-injected-by-js,它会在服务端运行时遍历已注册的 CSS 模块,拼出完整字符串 - 在 SSR 入口(如
render.ts)中,调用插件提供的getCssString()或类似 API,把返回值注入到模板的中 - 别用
替代——它会触发客户端二次请求,必然 FOUC
React/Vue 同构应用里样式漏了一层就白干
CSS 收集是显式树遍历,不是全局扫描。漏掉任意一个边界组件(Router、Suspense、高阶 Wrapper),对应样式就丢失,且无报错提示。
- React + styled-components:必须用
ServerStyleSheet,且collectStyles(必须包裹最外层,包括) 和所有异步边界 - Vue 3:
renderer.renderToString(app, { styleSheets: true })中styleSheets: true不可省略,否则context.styles为空 - 动态组件(
defineAsyncComponent或lazy())里的import './xxx.module.css'不会被自动收集,得提前预加载或手动触发样式注册
真正容易被忽略的是:CSS 收集时机必须与组件渲染完全同步——不是“渲染完再收集”,而是“边渲染边收集”。一旦你把样式提取逻辑放在 renderToString 调用之后,或者拆成两个独立步骤,就大概率漏掉异步/条件渲染分支里的样式。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











