PurifyCSSPlugin能识别BEM类名是因为它静态扫描HTML/JS中出现的完整类名字符串(如class="button__icon--loading"),并与CSS中对应选择器匹配;它不解析BEM语法,也不执行JS,故动态拼接类名会被忽略,且必须确保CSS已由MiniCssExtractPlugin正确提取并在processAssets阶段可用。

Webpack 本身不提取 BEM 类名,它只负责打包和转换;真正能“提取”BEM 类名的,是配合使用的 PurifyCSSPlugin 或自定义插件,但前提是类名必须以静态字面量形式出现在源码中(如 className="card__header"),且 CSS 文件已通过 css-loader 正确模块化或全局引入。
为什么 PurifyCSSPlugin 能识别 BEM 类名?
它不识别“BEM 语法”,只识别 HTML/JS 中出现的**完整、静态的类名字符串**。只要你的模板里写了 class="button__icon--loading",而 CSS 文件里有对应选择器 .button__icon--loading,PurifyCSS 就能匹配并保留它。
- 它依赖
glob.sync()扫描路径里的所有 HTML/JS/TS 文件,所以 JSX 中的className、Vue 模板中的class都要包含在paths配置里 - 不支持动态拼接:
className={`button__${state}`}或styles[`${block}__${el}`]会被完全忽略——PurifyCSSPlugin不执行 JS,只做字符串匹配 - BEM 的
__和--只是普通字符,没有特殊处理逻辑;但它们让类名更唯一,反而降低了误删概率
css-loader 必须开启 modules 才能保 BEM 语义
如果你用的是 .module.css + CSS Modules,css-loader 必须显式配置 modules: { enabled: true }(Webpack 5+),否则 BEM 类名不会被哈希隔离,PurifyCSSPlugin 扫描时可能误删——因为全局 CSS 中同名类太多,它无法判断哪个该留。
- 错误配置:
modules: true(旧写法,在 Webpack 5+ 会静默失效) - 正确配置:
modules: { enabled: true, localsConvention: 'camelCaseOnly' },确保button__icon在 JS 中仍可访问为styles.button__icon -
localIdentName: '[name]__[local]--[hash:5]'是底线:既保留 BEM 结构可读性,又避免哈希过长影响调试
ExtractTextPlugin / MiniCssExtractPlugin 顺序不能错
PurifyCSSPlugin 必须在 MiniCssExtractPlugin(Webpack 4+ 推荐)之后运行,否则它扫描不到最终生成的 CSS 内容。
立即学习“前端免费学习笔记(深入)”;
- Webpack 构建流程是:JS 解析 → CSS 提取 → CSS 输出 → 插件处理资产(assets)
-
PurifyCSSPlugin在compilation.hooks.processAssets阶段操作compilation.assets,此时MiniCssExtractPlugin已把 CSS 写入 assets,它才能读取并删减 - 如果插件顺序颠倒,你会看到 CSS 文件体积没变小,控制台也无报错——它根本没拿到有效 CSS 内容
BEM 类名是否被成功提取,不取决于命名多规范,而取决于三件事:HTML/JS 中是否写了静态类名、CSS 是否被正确提取进独立文件、PurifyCSSPlugin 是否在正确时机读到了它。最容易被忽略的是动态拼接类名和插件执行顺序——这两处一错,整个优化就失效了。


















