SCSS编译后CSS体积过大根本原因在于源码结构失控,而非未开启压缩;@extend爆炸、@import全量引入、@mixin无节制展开、嵌套过深导致内容冗余,compressed仅删空格换行注释,不合并选择器或剔除未用规则。

SCSS 编译后 CSS 体积变大,根本不是因为没开压缩,而是源码结构失控 —— @extend 爆炸、@import 全量引入、@mixin 无节制展开、嵌套过深,这些才是真凶。压缩只是“瘦脸”,不是“抽脂”。
为什么开了 outputStyle: 'compressed' 还是很大
因为 compressed 只删空格、换行、注释,不删重复声明、不剔未用类、不合并选择器。如果你的 SCSS 里写了 .m-1 到 .m-100,编译后就是 100 条规则,哪怕挤在一行,体积照旧。
- 检查输出 CSS 中是否反复出现同一组样式(比如
margin: 0.5rem出现 47 次)——大概率是@extend或循环生成导致 - 运行
gzip -c main.css | wc -c对比 gzip 后体积,若仍远超预期,说明内容冗余,不是格式问题 -
sourceMap: true会把 base64 映射追加到 CSS 末尾,轻松+100KB+,必须关掉
停用 @extend,改用 CSS 自定义属性
@extend 不共享声明,只拼接选择器。两个组件都 @extend %button-base,最终 CSS 就有两份完全相同的 padding 和 border-radius,cssnano 还无法合并它们,因为属于不同规则块。
- 仅对无状态、无上下文、能直接加到 HTML 的原子行为用
%占位符,例如%sr-only、%clearfix - 禁用含
:hover、@media、&__header结构的占位符 —— 它们必然触发组合爆炸 - 把间距、颜色、圆角等抽成
:root { --space-sm: 0.5rem; },组件内统一用margin: var(--space-sm),声明只存一份
用 @use 替代 @import,并手动导入子模块
@import 是文本拼接,没有模块边界;@use 才支持按需导入变量/mixin,且 Sass 能识别未调用项(虽不自动删,但为 Tree Shaking 提供基础)。
立即学习“前端免费学习笔记(深入)”;
- 别写
@import "bootstrap.scss"—— 它会引入全部 30+ 组件 - 改用
@use "bootstrap/scss/functions" as func、@use "bootstrap/scss/mixins" as mix,只加载真正需要的部分 - 确保
package.json中sideEffects字段正确声明:"sideEffects": ["*.scss", "src/styles/**/*.scss"],否则 Webpack 不敢删未引用的样式文件
构建阶段加 PurgeCSS,但必须配对时机和路径
PurgeCSS 不处理 SCSS 源码,只扫描已生成的 CSS + 模板文件,删掉未使用的完整选择器。它必须放在 Sass 编译之后、CSS 压缩之前。
-
content字段必须覆盖所有模板路径,例如["src/**/*.{vue,html,js}"],漏一个就可能保留整套未用组件样式 - 如果 JS 动态拼接类名(如
clsx('btn', isPrimary && 'btn-primary')),需在safelist中显式保留btn-primary - 不要试图让
PurgeCSS解决@mixin展开重复的问题 —— 那得从 SCSS 编写层改起
最容易被忽略的是:@extend 和 compressed 一起用,反而让 cssnano 失效;@use 导入了 mixin 却没调用,它仍会参与编译;sideEffects 写成 false 导致 url() 引用的字体/图片丢失。优化不是配个开关就完事,每一步都得卡准位置、看清副作用。


















