css 文件默认会被 tree shaking 误删,因为 import './index.css' 无导出、无引用,在 "sideeffects": false 时被判定为死代码而剔除;需在 package.json 中显式配置 sideeffects: ["*.css"] 声明其副作用。

CSS 文件默认会被 Tree Shaking 误删,必须显式声明副作用
为什么 import './index.css' 会导致样式丢失?
Webpack 的 Tree Shaking 是基于 ES 模块静态分析的,它只识别 import 和 export 的依赖关系。而 import './index.css' 没有导出任何值,也没有被其他代码引用——在 Webpack 看来,这就是“死代码”,尤其当 "sideEffects": false 时,整个 CSS 文件会被直接剔除。
常见现象包括:开发环境样式正常,生产构建后按钮没颜色、布局错乱、全局类名失效。
- 该问题与是否使用
css-loader/style-loader无关,只要模块没导出,且未声明副作用,就可能被删 - 即使 CSS 中含
@import或url(),也不会触发“被引用”判定 - PostCSS 插件(如 autoprefixer)不改变这一行为,它们作用于内容而非模块图
如何正确配置 sideEffects 告诉 Webpack “这个 CSS 不能删”
在项目根目录的 package.json 中设置 sideEffects 字段,明确列出所有含副作用的资源路径:
{
"name": "my-app",
"sideEffects": [
"*.css",
"*.less",
"*.scss",
"src/polyfills.js",
"src/assets/fonts/*.woff2"
]
}
注意点:
-
"*.css"匹配任意位置的 CSS 文件(包括node_modules中被import的),但不匹配.module.css(除非你额外加"*.module.css") - 路径是相对于
package.json的,不是 Webpack 配置里的context - 如果只写
false,表示“全项目无副作用”,CSS 必丢;写成true则完全禁用 Tree Shaking,不推荐 - 若使用 CSS-in-JS(如 Emotion),其生成的样式注入逻辑本身就有副作用,通常无需额外声明——但导入的纯 CSS 文件仍需列进
sideEffects
为什么不能靠 usedExports 或 /*#__PURE__*/ 解决 CSS 问题
usedExports 是 Webpack 的模块级标记机制,只对导出变量生效;/*#__PURE__*/ 是给 Terser 用的纯函数提示,两者都要求目标有明确的 export。而 import './a.css' 是语句(statement),不是表达式(expression),无法加注释,也无法被 usedExports 跟踪。
换句话说:
-
import { Button } from 'antd';→ 可以被usedExports分析,Button 未用则删 -
import './theme.css';→ 不产生导出,usedExports完全无视,只看sideEffects -
import styles from './Button.module.css';→ 有导出,但属于 CSS Modules,一般不会被删(因有命名导出),但仍建议纳入sideEffects显式保护
验证是否生效的最快方式
改完 package.json 后,执行生产构建并检查输出:
- 运行
npx webpack --mode=production --stats=verbose,搜索输出中是否含sideEffects: true对应的 CSS 模块 - 用
webpack-bundle-analyzer打开报告,确认 CSS 文件出现在打包结果里(而不是消失或变成空 chunk) - 手动删掉
sideEffects配置再构建一次,对比 HTML 页面是否真的“变白”了——这是最直白的副作用证据
真正容易被忽略的是:第三方 UI 库(如 Ant Design、MUI)内部的 import 'xxx/dist/xxx.css' 也会受你项目的 sideEffects 控制。如果你设了 "*.css",它们就安全;如果漏配,连 node_modules 里的 CSS 都可能被摇掉。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











