必须使用 dart sass(sass)而非已废弃的 node-sass,因其兼容 node 20、无需构建工具依赖;ci 中禁用 sass --watch,改用一次性编译命令并关闭 sourcemap;需清理缓存、锁定 node 与 sass/sass-loader 版本,并将 @import 迁移至 @use。

直接用 sass CLI 配合 CI 脚本就能跑通,不需要额外构建工具;但前提是必须用 Dart Sass(sass),不是已废弃的 node-sass——后者在 Node 20 环境下根本装不上,CI 会卡在依赖安装阶段。
确认项目用的是 sass 而非 node-sass
CI 失败最常见原因就是两者混用或残留旧包。执行 npm list node-sass sass 检查输出:
- 如果同时出现
node-sass和sass,立刻删掉node-sass:npm rm node-sass --save-dev - 如果只看到
node-sass,说明项目还在用旧链路,必须替换为sass:npm add sass --save-dev -
sass是纯 JS 实现,不依赖 Python/make/node-gyp,CI 容器里无需额外装构建工具
sass --watch 不适合 CI,改用一次性编译命令
CI 流程要的是可预期、可中断、无后台进程的构建行为。sass --watch 是开发时用的监听模式,在 CI 中会挂住不退出,导致流水线卡死。
- 正确做法是用单次编译:
sass src/scss/:dist/css/ --style=compressed --no-source-map -
--style=compressed生成压缩版,省去额外 postcss 或 clean-css 步骤 -
--no-source-map关掉 sourcemap(CI 通常不需要),避免因权限或路径问题报错 - 路径分隔符统一用正斜杠
/,Windows CI 镜像也认,反斜杠\在 YAML 中易被误解析
CI 脚本里必须清理缓存并锁定 Node 版本
本地能跑、CI 崩了,90% 是因为 node_modules 缓存污染或 Node 版本漂移。
- 在 CI 脚本开头加:
rm -rf node_modules package-lock.json,强制干净安装 - 显式指定 Node 版本:GitHub Actions 用
uses: actions/setup-node@v3+node-version: '20';GitLab CI 直接写image: node:20.15 - 避免 npm 缓存干扰:
npm ci --no-audit --no-fund,比npm install更可靠 - Docker 构建时,确保
RUN npm ci前工作目录已清空,旧层里的node_modules可能含损坏的二进制绑定
Webpack 项目里别让 sass-loader 和 sass 版本打架
如果你用 Webpack 打包,sass-loader 必须匹配 Webpack 版本,且底层依赖的仍是 sass 包。
- Webpack 5 对应
sass-loader@13.x,sass@1.77+;用^自动升级容易引入不兼容小版本 - 检查
sass-loader的 peerDependencies,它要求的sass版本范围必须和你装的一致 - 报错
this.getOptions is not a function就是sass-loader和 Webpack API 不对齐,降级或锁死版本即可 - CI 中建议固定版本:
"sass": "1.77.6", "sass-loader": "13.3.3",避免语义化版本隐性升级
真正容易被忽略的是:SCSS 文件里用了 @use 或 @forward 时,node-sass 根本不支持,而 Dart Sass 默认启用模块系统——CI 编译失败往往不是语法错,而是旧引擎压根不认识新语法。换完 sass 后务必验证所有 @import 是否已迁成 @use,否则部分文件可能静默跳过编译。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











