Chrome Coverage工具能直接标出未匹配任何元素的CSS规则,通过DevTools→More Tools→Coverage启动,刷新后以红/绿色标记未用/已用字节,但仅反映当前视图下的实际渲染情况,不检测伪类、媒体查询非触发状态及JS动态添加的选择器。

Chrome Coverage 工具能直接看到哪些 CSS 没执行
Coverage 不是猜,是真实运行时统计:它记录浏览器渲染过程中实际应用到的每一行 CSS 字节。打开 DevTools → More Tools → Coverage → 点击 Start instrumentation and reload,刷新页面后就能看到每份 CSS 文件里哪些行是红色(0% 使用)、哪些是绿色(100% 使用)。
注意三点:
- 必须覆盖所有交互路径:点击菜单、展开折叠面板、触发表单校验、切换暗色模式——Coverage 只统计当前视口和当前状态下的使用情况
- 单页应用要手动跳转到每个路由后再点
Reload coverage,否则只扫首页 - 媒体查询未命中当前屏幕尺寸时,对应规则会标红,但这不等于可删;需切不同 viewport 再测一遍
PurgeCSS 配错 content 就会误删样式
PurgeCSS 本质是字符串匹配器,它不解析 JS 逻辑,只扫描你配置的 content 路径下所有文件里的 class 名字。如果你漏写 .html 或 .js 文件,或者路径 glob 写成 src/**/*.ts 却没包含 .tsx,它就会把真实用到的 .btn-primary 当作死代码删掉。
常见踩坑点:
立即学习“前端免费学习笔记(深入)”;
- Vue/React 项目中动态拼接类名(如
class="text-{{ color }}"或className={`is-${status}`})必须加safelist,例如/^text-.+$/或/^is-.+$/ - Tailwind 用户别直接套用 PurgeCSS 配置,应改用
tailwind.config.js的content字段——它基于 AST 解析,比字符串匹配更可靠 - 构建后 CSS 体积没变?大概率是因为你在
bootstrap.min.css上跑 PurgeCSS——它只删源码里完全没出现的选择器,而 Bootstrap 类名常由 JS 动态注入,根本扫不到
Sass 编译阶段做按需导入,比事后清理更有效
与其让 PurgeCSS 在成品 CSS 上“抢救”,不如从 Sass 编译源头控制输出。不要在 main.scss 里写 @import "bootstrap/scss/bootstrap",改用显式链式导入:
@import "bootstrap/scss/functions";@import "bootstrap/scss/variables";@import "bootstrap/scss/mixins";- 只加真正用到的模块,比如
@import "bootstrap/scss/grid";,删掉carousel、tooltip等不用的组件
这样编译出来的 CSS 天然精简,PurgeCSS 压根不需要介入,也避开了动态类名识别失败的问题。
sourceMap 断链会导致 Coverage 定位失准
Coverage 标出某行 CSS 未使用,你想点进去看它来自哪个 SCSS 文件,结果跳转失败或行号错乱——这往往不是 Coverage 问题,而是 sourceMap 链断了。
关键检查项:
- CSS 文件末尾是否有合法
/*# sourceMappingURL=main.css.map */注释,且必须是最后一行、无空行、无其他字符 -
.map文件能否被浏览器直接访问(如http://localhost:3000/css/main.css.map),打开后sources字段是否非空、路径是否相对且可解析 - Vite 用户需同时开启两个开关:
css.devSourcemap: true和css.preprocessorOptions.sass.sourceMap: true;Webpack 用户确保sass-loader的sassOptions.sourceMap为true,且devtool不用cheap-module-source-map
没有可用的 sourceMap,Coverage 就只能告诉你“这行 CSS 没用”,但你没法快速判断它来自 _mixins.scss 还是 _buttons.scss,也就难以决定删还是留。


















