BEM 不支持 Tree Shaking,因 CSS 导入被视为副作用,打包器不解析内部选择器;PurgeCSS 等工具通过扫描源码中实际类名字符串实现安全清理,需正确配置 content、safelist 和 whitelistPatterns,并仅在生产环境启用。

BEM 本身不支持 Tree Shaking,CSS 文件根本不会被 Tree Shaking 处理 —— 这不是配置问题,是机制限制。
为什么 CSS 无法被 Tree Shaking
Tree Shaking 是 Webpack/Rollup 对 ES Module 的静态分析行为,依赖 import/export 的可追踪性。而 import './button.css' 在打包器眼里只是“有副作用的导入”,整份 CSS 被当作黑盒保留,内部选择器是否被使用,完全不解析。
常见错误现象:button--primary 在 JSX 里没出现过,但对应 CSS 规则仍完整保留在产物中;或开了 sideEffects: false 后整个 CSS 文件直接消失 —— 因为打包器根本不识别 CSS 内部结构。
真正起作用的是 PurgeCSS、UnoCSS 这类工具,它们不靠模块语法,而是扫描源码中实际出现的类名字符串(如 className="button button--primary"),再反向比对 CSS 文件里的规则。
立即学习“前端免费学习笔记(深入)”;
PurgeCSS 如何安全清理 BEM 修饰符
BEM 的 --modifier 类名(如 card--shadow-heavy)最容易残留:定义了但模板里从没用过。PurgeCSS 是唯一能系统清理它们的方案,但必须配准:
-
content路径必须覆盖所有模板来源,漏掉./src/**/*.tsx或./public/index.html就会误删 - 默认正则
/[\w-/:]+/会截断header__title--large中的双下划线和双短横,建议换用defaultExtractor或社区 extractor(如@fullhuman/postcss-purgecss的extractors配置) - 动态拼接的修饰符(如
clsx(`${block}--${size}`))必须加到safelist:例如safelist: [/--(small|medium|large)/] - 第三方库的 BEM 类(如
react-datepicker__day--selected)要放进whitelistPatterns,否则直接消失
开发环境千万别开 PurgeCSS
在 postcss.config.js 中必须用环境变量控制:
plugins: [
process.env.NODE_ENV === 'production' && require('@fullhuman/postcss-purgecss')({
content: ['./src/**/*.html', './src/**/*.tsx'],
safelist: [/^data-v-/],
})
].filter(Boolean)
否则热更新失效:你刚在 JSX 里写了 button--fluid,PurgeCSS 已经把它从构建结果里删掉了,浏览器里看不到新样式。
真正难的不是写对配置,而是确保所有修饰符类名都以可静态分析的方式出现 —— 比如禁止在 useEffect 里用字符串拼接生成 className,或通过 API 动态注入 class 字符串。这类行为会让 PurgeCSS 彻底失效,只能靠人工维护白名单,而白名单一长,就失去了自动化意义。


















