根本原因是Bootstrap全量加载导致大量未用样式残留,必须先通过Sass按需导入裁剪,再用PurgeCSS扫描源码收尾清理;直接处理bootstrap.min.css无效,因其无使用上下文且依赖data-bs-*属性和JS逻辑。

bootstrap.min.css 体积大不是压缩问题,是功能全量保留
直接换用 bootstrap.min.css 只能减少约 60% 字符体积,但所有未使用的组件样式(如 .carousel、.offcanvas、.tooltip)依然完整存在。gzip 后仍占 20–25KB,而其中可能 70% 的规则在你的页面里从未匹配过任何元素。
根本原因在于:它不看你的代码用了什么,只做机械压缩。哪怕你项目里只有 <button class="btn"></button>,bootstrap.min.css 里照样包含 @keyframes carousel-slide 和全部断点下的 mt-5 规则。
-
data-bs-toggle="modal这类属性触发的样式不会被 PurgeCSS 扫到,除非你让它扫描 JS/HTML 源码而非压缩后的 CSS - JS 动态拼接类名(如
el.className = 'btn btn-' + type)无法被静态分析捕获 - Vue/React 中条件渲染的 utility 类(如
v-if="show" class="d-block d-md-none")需显式配置content路径才能识别
为什么 PurgeCSS 直接扫 bootstrap.min.css 基本无效
PurgeCSS 是个「字符串匹配器」,不是「运行时分析器」。它只查源文件里是否出现过 "btn"、"d-flex" 这样的字面量,而 bootstrap.min.css 是编译结果,不含任何使用上下文。
更关键的是:Bootstrap 5+ 的行为依赖 data-bs-* 属性和 JS 初始化逻辑,这些不会转成类名出现在 HTML 字符串中。所以 PurgeCSS 扫完,反而会删掉真正生效的 .dropdown-menu 或 .visually-hidden —— 因为它们没在模板里“写死”。
立即学习“前端免费学习笔记(深入)”;
- 错误现象:
modal点不开、dropdown不展开、d-lg-none失效 - 构建后检查最终 CSS 是否还含
.carousel-inner或.modal-backdrop:如果有,说明 PurgeCSS 没起作用,或作用对象错了 - 正确目标不是处理
bootstrap.min.css,而是处理你用 Sass 编译出的、只含所选模块的 CSS
必须先走 Sass 按需导入,再让 PurgeCSS 扫描输出
这是唯一可靠路径。PurgeCSS 的价值,是在你已经剔除大部分冗余之后,再收尾清理那些模板里没显式写出、但 JS 或框架内部可能用到的边缘类名(比如 .show、.fade)。
操作顺序不能颠倒:
- 删掉所有
import 'bootstrap/dist/css/bootstrap.min.css'或@import "bootstrap/scss/bootstrap" - 新建
src/custom-bootstrap.scss,按顺序导入必需模块:@import "bootstrap/scss/functions"→@import "bootstrap/scss/variables"→@import "bootstrap/scss/mixins"→ 再按需加@import "bootstrap/scss/grid"、@import "bootstrap/scss/buttons" - 禁用不用的组件:注释掉
@import "bootstrap/scss/modal"、@import "bootstrap/scss/popover"等,比任何后处理都干净 - 精简
$utilities:如果你不用阴影,就从$utilitiesmap 中移除shadow;如果只用 xs/md 断点,就重设$grid-breakpoints
PurgeCSS 配置绕不开的三个硬性条件
即使走对了 Sass 路径,PurgeCSS 仍需补全三类盲区,否则会误删。
典型 purgecss.config.js 必须包含:
-
content: ['./src/**/*.{html,js,ts,vue,jsx,tsx}']:确保扫描模板和 JSX/TSX 中的类名字符串 -
defaultExtractor或自定义正则:匹配data-bs-*属性值(如data-bs-toggle="collapse"中的collapse) -
whitelist: ['show', 'collapsing', 'fade', 'dropdown-menu']:Bootstrap JS 内部使用的类名,模板里不出现,但运行时必需
漏掉任一条件,都可能导致下拉菜单不显示、折叠内容不切换、或者深色模式开关失效——这些不是 bug,是你没告诉 PurgeCSS “哪些类名虽然没写死,但 JS 会用”。
最易忽略的一点:PurgeCSS 不能替代 Sass 模块裁剪。它只是最后一道保险,而不是主力减负手段。真正砍掉 60% 体积的动作,发生在你删掉第 7 个 @import 的那一刻。


















