必须显式配置sassOptions.outputStyle: 'compressed'且sourceMap: false,因Sass默认outputStyle为'nested'、sourceMap默认开启,二者不随环境自动切换;若未手动设置,SCSS层输出冗余expanded格式并附加base64映射,导致后续压缩事倍功半。
必须显式配置 sassOptions.outputStyle: 'compressed',否则无论后续加多少压缩插件,SCSS 层输出的仍是冗余的 expanded 格式——这是体积失控的第一道闸门没关紧。
Webpack 5 不会对 CSS 自动启用压缩,哪怕 mode: "production" 已设。插件必须显式注册,且只对独立 CSS 文件起作用:
css-minimizer-webpack-plugin 不够,必须搭配 MiniCssExtractPlugin 提取 CSS;否则 CSS 还在 JS bundle 里,插件无目标可压optimization.minimizer 数组中,写进 plugins 字段会被完全忽略style-loader 注入 DOM,那根本没有生成 .css 文件,插件根本不会运行outputStyle 改成 'expanded',看编译出的 CSS 是否带缩进和空行——如果是,说明 Sass 配置已生效;再对比开启 css-minimizer-webpack-plugin 后文件大小是否变化sassOptions.outputStyle 是 Sass 层唯一的格式开关,它只删空格、换行、注释,不合并规则也不剔未用类——但它必须先执行。后续所有压缩(如 cssnano)都基于它输出的内容做二次处理。
'nested',不是 'compressed';它不感知构建环境,也不会被 css-minimizer-webpack-plugin 或 cssnano 反向影响module.rules.use[loaderIndex].options.sassOptions 下;Vue CLI 则嵌套在 css.loaderOptions.sass.sassOptions 里webpack.config.js 顶层或 css-minimizer 配置里)会被 Sass 编译器直接忽略--style=compressed --no-source-map,否则 base64 sourceMap 可能额外增加 100KB+开启 sourceMap 会让每个 SCSS 文件生成 base64 编码的映射内容,直接追加在最终 CSS 末尾。中等项目轻松多出 80–150 KB,远超压缩收益。
sourceMap: false 不是可选项,是必选项;别信某些版本“默认关闭”的传言——dart-sass 新版倾向保守开启additionalData 中若含 @debug 或 @warn,在 compressed 模式下会被静默丢弃;你本地看到日志,上线却毫无反应,容易误判逻辑失效_debug.scss,仅在 dev 环境 @use,且不参与 production 构建@debug/@warn 必须清理干净,或用条件包裹:@if $env == 'dev' { @debug '' }
真正卡住体积的从来不在“怎么压”,而在 Sass 源码结构本身:深层嵌套、滥用 @extend、全量 @import、循环生成工具类……这些在 compressed 阶段无法修复,只会被原样保留。压缩链必须是 Sass → PostCSS → cssnano,缺一不可,但源头控制永远比后期补救更有效。