必须显式设置sassoptions.outputstyle: 'compressed'并禁用sourcemap,否则sass默认输出'nested'格式且sourcemap默认开启,导致后续压缩插件只能处理冗余文本和base64映射内容,体积优化从第一步即失效。

必须显式设置 sassOptions.outputStyle: 'compressed' 并禁用 sourceMap,否则体积优化从第一步就失效——Sass 默认输出 'nested' 格式,后续所有压缩插件都只能在“胖输出”上徒劳加工。
为什么 outputStyle: 'compressed' 必须手动写
Sass 编译器不看环境自动切换格式,默认值始终是 'nested',不是 'compressed'。它不受 css-minimizer-webpack-plugin 或 cssnano 影响——你配了压缩插件,只是在处理 Sass 已经输出的冗余文本。这一步漏掉,等于让 10MB 的水先流进水管,再指望滤芯把水变少。
- Webpack 项目:必须写在
module.rules.use[loaderIndex].options.sassOptions下 - Vue CLI:要嵌套在
css.loaderOptions.sass.sassOptions里 - 写错位置(比如放在
webpack.config.js顶层或css.minimizer配置里)会被完全忽略 - 验证方式:临时改成
'expanded',观察编译出的 CSS 是否突然带缩进、换行、空行——如果是,说明配置生效了
sourceMap: false 不是可选项,是必选项
开启 sourceMap 会让每个 SCSS 文件生成 base64 编码的映射内容,直接追加在最终 CSS 文件末尾。一个中等项目轻松增加 80–150 KB,gzip 后几乎不压缩——因为 base64 是高熵内容。这不是“调试开关”,是体积暴增源。
- 别信某些版本(如
node-sass@7+)或文档里说的“默认关闭”,dart-sass当前稳定版(v1.82.0)仍默认true -
MiniCssExtractPlugin只控制是否提取 CSS 文件,不干预sass-loader是否注入 map 内容 - 开发调试应由 Webpack 的
devtool: 'source-map'统一提供 JS 层 sourcemap,样式定位足够覆盖
真正卡体积的从来不是空格,而是源码结构
--style=compressed 只删空格、换行、注释,不合并重复声明、不剔未用选择器、不简写数值颜色。实测开启后 gzip 提升通常不到 3%,而一个失控的 @extend 或 5 层嵌套就能让体积翻倍。
- 运行
grep -o "margin:" main.css | wc -l,如果数字远高于组件数,基本就是嵌套或@extend失控了 -
@extend %btn-base在 5 个上下文调用,会生成.header .btn、.modal .btn等 5 条独立规则,而非复用同一份声明 -
@import是文本拼接,哪怕只调用px2rem(12),也会把整个_utils.scss全塞进输出;改用@use才能按需加载 - 循环生成工具类:
@for $i from 1 through 100 { .m-#{$i} { margin: #{$i}px; } }直接产出 100 条规则,压缩也救不了
压缩链必须分两步:Sass → PostCSS → cssnano
Sass 命令本身不调用任何 PostCSS 插件,--load-path 或 --require 对 cssnano 完全无效。漏掉 PostCSS 这一环,等于只做了半程压缩。
- 推荐 Sass 输出
--style=expanded(更利于 PostCSS 解析嵌套和自定义属性),再交给postcss-cli或postcss-loader处理 -
cssnano的mergeLonghand、discardDuplicates、normalizeWhitespace等能力,只有在 PostCSS 管道里才能生效 - 若用
purgecss清理无用规则,务必确保它在 Sass 编译之后、cssnano 之前执行,并正确配置 HTML 入口和伪类白名单(如:hover、[data-theme])
最容易被忽略的是:Sass 输出阶段没控制好源码结构,后面所有压缩都是徒劳。体积问题不在“怎么压”,而在“写了什么”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











