PurgeCSS因仅扫描源码文本无法识别动态class(如btn-${type}),导致上线后样式丢失;Unocss通过AST分析运行时class,可捕获JS生成、条件拼接及v-html中的类名,支持attributify和深度Vite集成,但需注意preset冲突、shortcuts膨胀及@layer兼容性问题。

为什么PurgeCSS在Vue项目里删不干净class
它只扫描源码文本,不执行JS逻辑,遇到动态拼接的class就直接漏掉。比如v-bind:class="['btn', `btn-${type}`]",btn-primary这种就不会被识别。
常见错误现象:上线后按钮样式突然消失、部分组件UI错乱,但本地开发一切正常。
- 确保
content配置包含所有模板文件路径,包括.vue、.html甚至markdown(如果用VitePress) - 对动态类名,得手动加白名单:
safelist: [/^btn-/, /^text-/] - 若用了
tailwindcss/nesting或@apply,需确认PostCSS插件顺序——PurgeCSS必须在Tailwind之后运行
Unocss为何能绕过“扫描文本”这个死结
它不依赖文件内容扫描,而是靠运行时解析class字符串本身,在构建阶段做AST分析。只要最终HTML里出现的class,它就能收进来,包括JS生成的、条件拼接的、甚至v-html注入的。
使用场景:中后台系统里大量用el-button + :type绑定,或者用className做主题切换。
立即学习“前端免费学习笔记(深入)”;
- 开箱即用支持
attributify模式:<div class="m-4 p-2 text-red-500"></div> → <div m="4" p="2" text="red-500"></div>,不用写冗长class - 和Vite深度集成,热更新快;但Webpack需额外配
unocss-webpack-plugin - 注意
presets选择:用unocss/preset-attributify就别再启unocss/preset-tailwind,否则规则冲突
build后CSS体积差一倍?别只看gzip前大小
Unocss默认输出的是按需生成的原子类,而PurgeCSS输出的是原始Tailwind的精简版。前者更小,但可能因类名组合爆炸导致CSS规则数飙升——尤其在用theme自定义颜色/间距时。
性能影响:Unocss的shortcuts功能写btn="primary px-4 py-2 rounded"很爽,但每条shortcut都会生成独立CSS规则,滥用会拖慢渲染。
- 检查
dist/assets/index.xxxx.css实际字节数,别信打包工具控制台的“estimated” - PurgeCSS可配合
cssnano做二次压缩;Unocss建议关掉preflights(重置样式)——如果你项目已用Normalize或现代CSS重置 - 开启
extractor扩展时小心:某些富文本编辑器插入的class可能被误提,导致线上样式漂移
迁移时最易忽略的兼容点:@layer与作用域
Unocss默认不支持@layer components这类Tailwind语法,它的layers是另一套概念。而PurgeCSS完全兼容,只要Tailwind能认,它就能删。
容易踩的坑:把旧项目从PurgeCSS切到Unocss后,发现@layer base里的h1样式没了,或者scoped样式里写的.foo .bar组合选择器失效。
- Unocss里想复用原有
@layer逻辑,得改用rules数组手写,或启用unocss/preset-wind并关闭preflights -
<style scoped></style>中用class="text-lg"没问题,但写class="hover:text-blue-500"可能不生效——需确认是否启用了hover变体支持 - 第三方UI库(如Naive UI)的
class命名不规范时,PurgeCSS靠safelist硬保,Unocss得靠rules或extractors显式捕获
真正麻烦的不是选哪个工具,而是你项目里有多少“看不见的class”——它们藏在JSON配置、CMS字段、用户输入甚至埋点SDK里。这些地方,两个工具都救不了你,只能靠测试环境跑真实页面截图比对。


















