使用 Dart Sass 代替 Node Sass

July 08, 2019

2020-10-27 更新:Sass 官方已在 2020-10-26 正式宣布弃用 LibSass,并推荐使用 Dart Sass https://sass-lang.com/blog/libsass-is-deprecated

从 node-sass 迁移到 dart-sass

为什么要换掉 node-sass

对于使用 Scss 的前端项目,经常会在 yarn install 过程中出现 node-sass 安装失败的情况,又或者切换了 Node.js 版本发现 node-sass 需要编译才能用,如果使用 alpine 版本的 docker 镜像安装 node-sass 还会遇到由于缺少 Python 和各种依赖导致 node-sass 编译失败的情况,又或者在国内由于网络原因导致 node-sass 需要的二进制文件下载不下来而 build 失败。

那么为什么 node-sass 会有这么多问题呢,这就要涉及到另一个项目: LibSass,在很长一段时间里,用 C/C++ 写的 LibSass 一直是 Sass 语言的一个主流实现,其他语言如果要使用 LibSass,需要有建立一个 wrapper 才可以,在 Node.js 环境里,这个 wrapper 就是广为人知的 node-sass,它的作用就是在 Node.js 环境里用 JavaScript 去调用 LibSass,问题的本质还是在 Node + LibSass 造成的复杂性。

Dart Sass

上面的这些问题一直广受 JS 社区广大用户的诟病,Sass 官方也意识到了这个问题,所以现在 Sass 官方宣布使用 Dart Sass 作为 Sass 的主要实现:

Dart Sass is the primary implementation of Sass, which means it gets new features before any other implementation. It's fast, easy to install, and it compiles to pure JavaScript which makes it easy to integrate into modern web development workflows.

和 LibSass 不同,Dart Sass 最终是被编译成纯粹的 JS 代码来执行的,所以如果使用 Dart Sass,上面那些使用 node-sass 出现的问题就不会再遇到了,另外 Dart Sass 和 node-sass 在暴露给用户的 API 方面是保持一致的,这表示几乎可以无痛迁移。

sass-loader 从 9.0.0 版本开始已经默认使用 Dart Sass 了,用户不需要做任何操作,如果你因为一些原因暂时无法升级 sass-loader 到 v9 版本,可以参考下面的做法来手动启用 Dart Sass。

这里用 webpack 举例:

# 记得删掉 node-sass
yarn remove node-sass

# 安装 dart sass (不要问我为什么包名是 sass)
yarn add sass -D

# 如果你的 sass-loader 版本小于 7.2,需要手动更新到 >= 7.2 的版本
yarn add sass-loader@7

修改 webpack 配置,在 sass-loader 的 options 里加一行 implementation: require('sass')

{
  loader: 'sass-loader',
  options: {
    implementation: require('sass'),    sourceMap: true
  }
}

这样就配置好了,使用上感受不到差异,不过再也不会遇到 node-sass 安装的各种问题了,性能方面,我在自己的项目里也进行了多次测试对比,从我的测试结果和 Dart Sass 给出的 perf 来看,总体性能和 libsass 相比几乎一致,完全不用担心。

如果你喜欢我的内容,请考虑请我喝杯咖啡☕吧,非常感谢🥰 。

If you like my contents, please support me via BuyMeCoffee, Thanks a lot.