Webpack 5 默认不支持 CSS Tree Shaking,需依赖 purgecss-webpack-plugin 或 Unocss 等工具实现;PurgeCSS 通过扫描源码中实际使用的类名来剔除未用样式,但对动态 class 名需显式配置 safelist 或改用 CSS Custom Properties;Vite 用户推荐直接使用 Unocss,其按需生成 CSS,天然规避动态类识别问题。

Webpack 5 默认不支持 CSS Tree Shaking,得靠插件和约定
Webpack 本身只对 JS 模块做静态分析和死代码消除,import './button.css' 这种语句会被视为有副作用(side effect),即使 CSS 里定义的类名在 JS 中完全没被引用,Webpack 也会保留整个文件。真正能剔除未使用 CSS 的,不是 Webpack 内置能力,而是依赖 purgecss-webpack-plugin 或 unocss 这类工具,在构建时扫描 HTML/JS 中实际出现的类名,再反向过滤 CSS。
常见错误现象:build 后 CSS 文件体积几乎不变,DevTools 里仍能看到大量灰色未命中样式;或启用插件后部分样式突然消失——通常是因为类名是动态拼接的(如 className={`btn-${type}`}),没被正确识别。
- 必须显式配置哪些路径下的 HTML/JS 需要被扫描(例如
src/**/*.html、src/**/*.{js,ts,jsx,tsx}) - 避免在 CSS 中写过于泛化的选择器(如
div p),这类无法被 PurgeCSS 安全删除 - 若用 Tailwind,优先走
content配置 +TAILWIND_MODE=watch,别套用 PurgeCSS 插件重复配置
PostCSS + purgecss 是最轻量可控的落地方式
不需要动 Webpack 配置也能生效,适合已有构建流程但想快速验证效果的项目。只需在 postcss.config.js 中加入 purgecss 插件,并指定内容源和 safelist(白名单)。
示例配置片段:
module.exports = {
plugins: [
require('purgecss')({
content: ['./src/**/*.{js,jsx,ts,tsx,html}'],
css: ['./src/**/*.css'],
safelist: [/^bg-/, /^text-/, /data-theme/], // 防止正则类名被误删
defaultExtractor: content => content.match(/[\w-/:]+(?<p>注意点:</p>
-
defaultExtractor是关键,Tailwind 默认用它提取类名;若你用的是 BEM 或自定义命名规范,可能需要重写这个函数 -
safelist不仅填字符串,更推荐用正则匹配动态类(如/^is-/匹配所有is-active类) - PurgeCSS 不处理
@import的 CSS 文件,所有待分析的样式必须是最终打包进输出的 CSS 字符串
动态 class 名必须显式声明,否则 100% 被删
这是最容易翻车的地方。像 className={`card card--${size} card--${theme}`} 这种写法,PurgeCSS 默认只看到字面量 card,而 card--sm、card--dark 在源码中没作为完整字符串出现,就会被干掉。
解决办法只有两个方向:
- 在
safelist中补全所有可能组合(适合枚举有限,如 size 只有sm/md/lg) - 改用
clsx或classnames并配合/* purgecss start ignore */注释块包裹动态部分(需插件开启keyframes和fontFace以外的 ignore 支持) - 更彻底的方案:把动态逻辑收口到 CSS Custom Properties,用 JS 控制
style属性而非 class 名(此时 PurgeCSS 完全不介入)
Vite 用户直接上 unocss,比手动配 PurgeCSS 更稳
Unocss 不是后处理剔除,而是按需生成 CSS。你在模板里写 class="text-sm p-2 bg-blue-500",它就在构建时生成对应 CSS 规则,没写的就不会存在。天然规避动态 class 识别难题,也无需 safelist。
接入要点:
- 安装
@unocss/preset-uno和unocss,在vite.config.ts中添加unocss()插件 - 确保
src/main.ts或入口 JS 中有import 'uno.css'(这是虚拟入口,实际无此文件) - 若原有项目已用 Tailwind,可先开
presetWind兼容,再逐步迁移到presetUno的原子化写法
注意:Unocss 对 class 属性的解析基于 AST,不支持字符串拼接(`p-${size}` 依然无效),但它提供 shortcuts 和 theme 配置来覆盖这类需求,灵活性其实更高。
真正难处理的从来不是工具链,而是“运行时才决定样式”的场景——比如 CMS 输出的富文本、用户自定义主题色、A/B 测试开关。这些地方 CSS 就不该靠 Tree Shaking 去减,而该用 style 标签注入、CSS-in-JS 或独立主题包加载。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











