你还在忍受node-sass的苦吗,何不尝试dart-sass的甜?

什么是Sass?

Sass是一种CSS预处理器语言,能给CSS增加一些有趣、新颖的特性。目前,Sass可以说是最成熟、稳定,且强大的CSS预处理语言。

当我们在开发时,如果样式表变得越来越大,结构复杂度越来越高,难以维护时。就需要Sass这种强大的预处理器语言,帮助我们写出高健壮性,易维护的CSS。Sass提供了像嵌套(nesting)、混入(mixins)、继承(inheritance)等非常好用的能力,而这些在原生CSS是不存在的。

LibSass

Sass作为CSS预处理器语言,有多种语言版本的实现。而LibSass移植于Ruby Sass CSS 编译器实现,使用C++实现。相较于Ruby Sass和其他替代性的实现版本,LibSass性能表现得更好。

node-sass

上面提到了LibSass是Sass的C++实现。node-sass库提供了nodejs环境下绑定到LibSass的能力。node-sass能够将 .scss 文件高效自动地编译成css。

尽管node-sass编译scss文件又快又好用,但是在开发和部署时,通过npm安装依赖包时,却很容易安装失败。

因为node-sass是一个 c++ 模块,安装的时候需要和node版本对应,不然就会编译报错。兼容性也是个问题。

于是乎,Sass官网已经在力推Dart实现的版本了。

Dart Sass

上文提到node-sass底层依赖于libsass,安装起来比较麻烦。尤其对使用Windows的用户来说,它还会强制用户安装python2和Visual Studio,否则无法编译成功。

那么为什么dart-sass更容易安装呢?因为它能编译成纯JavaScript包,发布到npm上,因此可直接在node环境中使用,且和node版本无关,无需担心兼容问题。

我们通过npm install时,指定安装的包名是sass,而不是dart-sass。因为最早它在npm上是以dart-sass的名字发布的,而现在已正式更名为sass。在npmjs官网上查看dart-sass库,可以看到如下提示包名已被重命名为sass。

This package has been renamed to 'sass'.

Sass官方也提到,已采用dart-sass作为未来的主开发方向。而且在社区中已稳定运行了很长时间,基本不会踩坑。

通过以下命令,可以轻松替换node-sass:

npm uninstall node-sass

npm install sass -S -D

npm install --save-dev sass

为什么选择Dart语言实现呢?

引述Dart Sass在github官网的介绍。Dart Sass取代Ruby Sass作为Sass语言的标准实现。选择Dart有以下好处:

  • 够快。Dart VM性能很强,表现出色。比Ruby快,比肩C++。
  • 移植性好。Dart VM没有外部依赖,能够将应用编译成独立的快照文件,所以分发后的Dart Sass仅仅包含三个文件(VM,快照和包装器script)。Dart还可以编译成JavaScript,通过npm分发Sass,这也是大多数用户使用Sass的方式。
  • 容易编写。Dart是比C++更高级的语言,意味着省去了大量麻烦的内存管理和构建系统。而且Dart是静态类型的,相比Ruby,做起大型重构来。更有底气。
  • 更助于代码贡献。Dart比Ruby容易学得多,而且Google的很多Sass用户已很熟悉Dart语言。代码贡献者越多,项目发展会更快且更持续。

这么看来,Dart Sass可真香。

Nuxt项目使用dart-sass

在nuxt项目中,通过设置build.loaders.scss的值,配置自定义.scss文件编译器。

const Sass = require("sass");
const Fiber = require("fibers");

const customSass = {
  implementation: Sass,
  sassOptions: {
    fiber: Fiber,
  },
};

module.exports = {
  telemetry: false,
  build: {
    loaders: {
      cssModules: {
        modules: {
          localIdentName: "[hash:base64:6]",
        },
      },
      // 此处设置scss处理器
      scss: customSass,
    },
  },
};

上面配置中,使用到了fibers包。Fibers有时又叫协程,通过其暴露的API,能够在单线程中,实现多个调用栈的相互跨越。这个能力可以让同步代码库,很好地在异步环境中运行。

在dart-sass的使用示例中提到,Dart Sass目前支持render() 和 renderSync() 函数。而renderSync() 比 render() 快两倍,这是由于异步回调带来地开销。为了消除这种开销,在render() 中,可以使用fibers包来异步地调用同步导入的代码。

详见:https://sass-lang.com/dart-sass

sass dart-sass node-sass