本文转载自微信公众号「前端司南」,作者Tusi。转载本文请联系前端司南公众号。
众所周知,node-sass 是一个非常棒的工具,是前端工程师组织 CSS 的一个神兵利器。然而,用过的朋友都知道,node-sass 是让人既爱又恨!你爱它,因为它赋能了 CSS 工程化;你恨它,因为有时候你搞不懂它为什么又出差错了。我最近就在生产环境新踩了两次 node-sass 的坑,这让我下定决心放弃 node-sass。
什么是node-sass?
虽然 node-sass 是一个熟悉的老朋友了,但是还是有必要介绍一下。
Node-sass is a library that provides binding for Node.js to LibSass, the C++ version of the popular stylesheet preprocessor, Sass.
It allows you to natively compile .scss files to css at incredible speed and automatically via a connect middleware.
从上面的介绍可以知道,node-sass 是一个 nodejs 环境下提供的一个 Bridge,它提供了调用 LibSass 的能力(而 LibSass 是一个 C++ 实现的样式预处理器)。
ps: 可以看到,node-sass 并不完全是 javascript 实现的,而是借助了 C++ 的能力,毕竟编译型语言还是速度快啊。
Round1:安装 node-sass
刚进入前端领域的朋友,可能都问过这么一个问题:为什么我的 node-sass安装失败了?
在网上搜索这个问题,你会找到答案,其中一个是使用 cnpm,但我用过感觉怪怪的,最早是使用 Angular4 时,执行ng eject发生了很多错误。
后面就一直用的设置 npm 淘宝镜像源的方式处理这个问题,同时这也是解决npm install下载卡顿或失败的一个技巧,毕竟有些包被墙了。
npm config set registry https://registry.npm.taobao.org
但解决了这个问题,也不是说就万事大吉了...
Round2:node-sass和node版本不兼容
一般来说,个人电脑的 NodeJS 环境安装好了后,很久都不会想着去升级。
不过我前段时间去研究 Vite 的时候,发现我的 NodeJS 版本已经不满足条件了。
Compatibility Note
Vite requires Node.js version >=12.0.0.
于是乎,我就升级了 NodeJS 版本。
但是,当我运行一些旧项目的时候,我发现,项目报错了。
- Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
- Error: Node Sass does not yet support your current environment: Windows 64-bit with Unsupported runtime (83)
- For more information on which environments are supported please see:
- https://github.com/sass/node-sass/releases/tag/v4.13.0
粗略一看,报错信息说的是 NodeSass 不支持当前运行时环境,我猜这肯定是跟 NodeJS 版本不匹配了。我首先检查了下我的 NodeJS 版本。
- nove -v
- v14.16.0
嗯,是新版本没错了。
于是就去 github 上查了下 node-sass,发现确实还是这么一回事,node-sass@4.13.0 版本真的不支持 node@14,惨!
其实,我只要把 NodeJS 版本降低到 13,问题也能得以解决。
但我觉得这还是有问题的。新项目要求高版本 NodeJS,而旧项目需要低版本 NodeJS,我本地只有一套 Node 环境,这样就出现了矛盾点,看来开发环境也比较需要容器化。
经大佬提醒,还有 nvm 可以管理 node 版本。
虽然这个问题也不能完全算是 node-sass 的锅,但谁叫它不支持 node@14 呢?用着还是不爽!
Round3:node-sass: Command failed
这是我上个月在生产环境跑 CI/CD 时遇到的一个问题。
- error /builds/coollu-r-d/coollu-fe/xkgj_web/node_modules/node-sass: Command failed.
后面还跟了一堆错误信息。
即便我已经是在 Docker 容器里执行 build 任务了,也就是说没有上面那个和 Node 版本不兼容的问题,但还是遇到了一次又一次的报错,这谁能顶得住呢?
使用Dart Sass
Dart Sass 是 Sass 官网力推的工具,它包括了基于 Dart VM 的命令行工具,以及基于 Node 的纯 Javascript 实现。前者说的 Dart VM 就是现在很火的 Flutter 选择的编程语言 Dart 的虚拟机;而后者的出现是为了能快速与 Node 环境下现有的工作流集成,比如 webpack,gulp等。Dart Sass的命令行工具是比 Javascript Library性能更好的,但是为了快速对接 webpack 等工具,我们目前一般通过npm install --save-dev sass直接使用 sass 的 Javascript Library。
改用 Dart Sass 后,不管是安装还是兼容高版本 Node 这块,都没有什么问题,总的来说,使用体验还是非常棒!
Dart Sass 是我们对它的习惯称呼,最早它在 npm 上的确是以 dart-sass 的名字发布的,不过现在它已经更名为 sass 了。
换Dart Sass后,我要做些什么
众所周知,在 Vue 项目中,scoped 样式是会通过一个哈希化的属性选择器进行隔离的(比如[data-v-67c6b990]),如果希望做样式穿透,在Vue@2中会用到/deep/深度选择器。
注意,/deep/本身是作为一个 CSS 的提案(好像是用于解决 web components 的样式穿透问题,用 Angular 的时候简单了解过),后面又被废弃了,而 Vue 的 /deep/跟 CSS 的/deep/不是同一个概念!考虑到用户容易误解 Vue 的/deep/和 CSS 被废弃的/deep/提案是一个东西,也就会误认为 /deep/是一个不可用的特性,Vue 也出了 RFC 针对这块做调整,后面也就有了::v-deep。
使用 Dart Sass 后,可能会在运行开发环境时遇到不支持/deep/的问题,需要改用::v-deep,简写就是:deep(selector),比如:
- :deep(.foo) {
- position: relative;
- }