tree shaking 不能直接作用于 css,因其依赖 es module 静态分析,而 css 无导出语义且打包器不解析其内容;真正有效的方案是 purgecss 或 unocss 等基于模板中实际类名匹配的工具。

Tree Shaking 能不能直接作用于 CSS
不能。Tree Shaking 是 JavaScript 打包器(如 Webpack、Rollup)基于 ES Module 静态结构做的死代码消除,它依赖 import/export 的可分析性。CSS 没有模块级导出语义,也没有运行时执行路径,所以打包器默认**完全不分析 CSS 内容是否被使用**——import './styles.css' 会被当作副作用导入,整个文件照单全收。
为什么 purgecss 或 unocss 才是实际解法
真正能删未用 CSS 的,是基于“源码中哪些类名/选择器实际出现”做白名单比对的工具。它们不依赖模块语法,而是扫描 HTML、JSX、Vue SFC 等模板中的字符串字面量(比如 class="btn primary"),再与 CSS 中的规则匹配。
-
purgecss:需手动配置内容源路径和提取器,适合传统项目;注意content路径漏写会导致大量误删 -
unocss:按需生成 CSS,本质是“用到才生成”,无冗余问题;但要求重构 class 写法为原子化(如text-center p-4 bg-blue-500) - 两者都不处理动态拼接的 class(如
class={`btn ${isActive ? 'active' : ''}`}),需用safelist显式保留
Webpack + PostCSS 场景下如何接入 PurgeCSS
在 postcss.config.js 中启用 @fullhuman/postcss-purgecss 插件是最轻量方式,无需改构建配置主体:
module.exports = {
plugins: [
require('@fullhuman/postcss-purgecss')({
content: [
'./src/**/*.html',
'./src/**/*.vue',
'./src/**/*.jsx',
'./src/**/*.tsx'
],
safelist: [/^data-v-/], // 保留 Vue scoped style 的属性选择器
defaultExtractor: content => content.match(/[\w-/:]+(?
- 务必检查
content是否覆盖所有模板文件,尤其注意.svelte、.astro等新格式需额外添加 -
defaultExtractor默认正则不匹配带中划线的 BEM 类(如header__title--large),建议换用regex或改用社区 extractor - 开发环境建议关闭 PurgeCSS(通过
process.env.NODE_ENV === 'production'控制),否则热更新样式会丢失
为什么 CSS-in-JS 库(如 Emotion、Linaria)能天然支持 Tree Shaking
因为它们把样式定义转成了 JS 函数调用或 tagged template literal,例如:css`color: red;` 或 styled.div`font-size: 14px;`。这些调用可被打包器识别为“可能未引用”,只要没被任何组件 import/use,对应样式逻辑就会被摇掉。
- 但前提是:样式必须定义在独立的 JS 文件中,且通过命名导出(
export const myStyle = css`...`),而非直接在组件内联写 - Linaria 还支持编译期提取,生成纯 CSS 文件,此时又回到需要 PurgeCSS 的路径
- Emotion 的
cssprop 如果配合 Babel 插件,会把样式内联到 DOM,无法摇,但也不需要外部 CSS 文件
safelist,且一旦漏加,线上就丢样式。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











