Sass 升级之旅

# 初代 Sass

Sass 最早是 2006 年由 ruby 开发的

而 ruby 是一门解释型语言,所以前端开发想编译 sass 就需要在本地安装 ruby。

后来,随着 Node.js 的出现推动了前端工程化的发展,也就是用 Node.js 来写前端用的编译打包等工具链。

而 Node.js 只支持 c++ 这种编译型语言的扩展包,ruby sass 就用不了了,所以出现了后来的 node-sass。

直到 2019 年 3 月,ruby sass 宣布不再维护,sass 最早的编译器退出历史舞台。

# 二代 Sass

sass 社区里有人用 c++ 实现了 sass 的编译器,叫做 LibSass,这个东西和 node 做了集成,就是 node-sass 这个包。

node-sass 让我们可以在 Node.js 里通过 api 来编译 sass 代码,顺应了前端工程化的大潮流。

而且 node-sass 是用 c++ 写的,编译速度比 ruby sass 快很多。

只不过,node-sass 因为是一个 c++ 模块,所以安装的时候要和 node 版本对应,不然就会编译报错,这点比较麻烦。

在 github 可以查到 node 和 node-sass 的版本对应关系:

NodeJS Supported node-sass version Node Module
Node 20 9.0+ 115
Node 19 8.0+ 111
Node 18 8.0+ 108
Node 17 7.0+, <8.0 102
Node 16 6.0+ 93
Node 15 5.0+, <7.0 88
Node 14 4.14+, <9.0 83
Node 13 4.13+, <5.0 79
Node 12 4.12+, <8.0 72
Node 11 4.10+, <5.0 67
Node 10 4.9+, <6.0 64
Node 8 4.5.3+, <5.0 57
Node <8 <5.0 <57

2020-10-27,Sass 官方团队正式宣布 Libsass 将弃用,以及基于它的 Node Sass 和 SassC,并且建议用户使用 Dart Sass。

为何弃用呢?主要是因为维护速度跟不上了。很多 css 的新特性 Libsass 并不支持,而且社区出现了 dart-sass 这个对 css 新特性支持更好的 sass 编译器,随着时间的推移,node-sass 与 dart-sass 相比在 CSS 新特性支持上差距越来越大。

所以最终官方团队不得不选择弃用 node-sass.

# 三代 Sass

dart-sass 是用 dart 来写的 sass 编译器。dart 可以编译为 js,所以它提供的 npm 包也是 js 的,它不需要像 node-sass 一样和 node 版本有绑定关系。

因为 dart-sass 的 npm 包的编译是用 js 做的,所以在编译速度上会比 node-sass 慢,但是它主要优势在对 css 的特性支持的全,而且因为是 js 包,安装很方便。

dart-sass 代表着未来,也是被官方推荐的 sass 编译器。最新的 sass 包也使用的是 dart-sass.

# 总结

其他两款 css 预处理器 less、stylus 的编译器都是 js 写的,而 sass 它的三代编译器分别是 ruby、c++、dart 写的,都不是 js。

从性能的角度考虑,无疑是 node-sass 性能最强。

但在墙内 node-sass 有安装问题,而且也有和 node 版本绑定关系的问题,安装使用比较麻烦。

目前我们设计平台组基本使用的还是 node-sass, node 版本也比较低,要升级 node 的同时也要升级 node-sass,比较麻烦

建议慢慢升级为 dart-sass, 面向未来,拥抱新特性!

当前我们项目中 node-sass 代码里的部分深度选择器语法不被 dart-sass 支持。因为:

  • dart-sass 只支持 : : v-deep
  • node-sass 支持 /deep/ 和 : : v-deep

所以在开发过程中,建议开发者使用 : : v-deep 摒弃 /deep/ 这种写法,为未来升级做好准备!