因为PurgeCSS不扫描node_modules中的CSS,也不解析import语句,仅从配置的content路径中提取明文类名;未在源码中显式出现的第三方库类名(如ant-modal)必须通过safelist精确匹配或正则保留。

为什么直接 import 的第三方 CSS 会被全删?
PurgeCSS 不扫描 node_modules 下的 CSS 文件,也不解析 import 'bootstrap' 这类语句本身——它只从你配置的 content 路径里提取字符串字面量类名(比如 class="ant-btn" 或 className="swiper-slide")。没在源码里明文出现的类,哪怕组件内部实际生成了,PurgeCSS 也完全不知道。
safelist 必须匹配最终渲染的 class 名
白名单不是“写个前缀就完事”,必须和浏览器最终 DOM 上出现的 class 完全一致。Ant Design 的 Modal 渲染出 ant-modal 和 ant-modal-content,那你就得写 'ant-modal' 和 'ant-modal-content',或者用正则 /^ant-modal/;写成 /ant-/ 可能误保 ant-input 等不用的类,写成 'ant' 则完全不匹配。
常见错误包括:
- 漏掉连字符或大小写:如写
'swiperSlide'而非'swiper-slide' - 正则未加锚点或转义:如
/bg-blue-500/匹配my-bg-blue-500-text,应写/^bg-blue-500$/ - 忽略动态前缀:Tailwind 的
dark:xxx、group-hover:xxx需单独列入safelist或启用defaultExtractor
Webpack 中插件顺序和路径必须严格正确
用 purgecss-webpack-plugin 时,paths 必须是绝对路径,且要覆盖所有可能生成类名的地方:
立即学习“前端免费学习笔记(深入)”;
- JSX/TSX 中的
className字符串 - HTML 模板里的
class属性 - Vue 的
class绑定、v-bind:class字面量部分
同时确保插件放在 MiniCssExtractPlugin 之后、OptimizeCSSAssetsPlugin 之前;否则 CSS 还没被提取出来,PurgeCSS 就去扫空文件了。
动态类名不能靠猜,得喂进 safelist 或改提取器
像 class={`btn btn-${type}`} 或 className={styles[`text-${size}`]} 这种,PurgeCSS 默认提取器根本不会拆解变量拼接逻辑。你有三个选择:
- 把所有可能值列进
safelist:['btn-primary', 'btn-secondary', 'text-sm', 'text-lg'] - 用正则覆盖模式:
{ pattern: /btn-(primary|secondary|danger)/ }、{ pattern: /text-(sm|md|lg)/ } - 换支持 AST 的提取器(如
vite-plugin-purgecss或自定义defaultExtractor),但成本高、兼容性差
别指望 “配完就稳”——第三方库的 class 命名策略、版本升级带来的类名变动、SSR 与 CSR 渲染差异,都会让白名单失效。上线前务必检查 DOM 元素是否缺失样式。


















