使用 Dart Sass 替代 Node Sass

有一个小程序项目使用了 WePY 1.0 版本,该版本使用了 node-sass 作为它的 sass 编译器,而且 node-sass 是 wepy-compiler-sass 的依赖项存在,无法通过在项目目录卸载 node-sass,安装 sass 的方法来完成编译器替换。

研究了下,找到了下面这个曲线救国的方法:

我使用的包管理器是 pnpm,而 pnpm 可以通过 .pnpmfile.cjs 文件声明钩子来修改安装 package.json 中的依赖项。

以下代码就实现了在安装项目依赖时,将所有的 node-sass 引用修改为 sass@^1.58.3

function readPackage(pkg) {
  if (pkg.dependencies && pkg.dependencies['node-sass']) {
    pkg.dependencies['node-sass'] = 'npm:sass@^1.58.3'
  }
  return pkg
}

module.exports = {
  hooks: {
    readPackage
  }
}

完成了编译器的替换,开启项目实时编译,出现了一个报错:

[Error] Error: Can't find stylesheet to import.
  ╷
1 │ @import './fonts.wxss';
  │         ^^^^^^^^^^^^^^
  ╵
  src/styles/common.scss 1:9  @import
  src/app.wpy 2:10            root stylesheet

原来是项目的 SCSS 文件 @import 了小程序的 WXSS 文件。

在 node-sass 中,.wxss 后缀的文件可以被当作 CSS 文件导入,而 dart-sass 是不允许这种操作的。

对于这个问题,可以通过修改 wepy.config.js 配置文件中的 sass 选项来修复:

const fs = require('fs');
const path = require('path');

module.exports.compilers['sass'].importer = (url, prev) => {
  const file = path.resolve(path.dirname(prev), url);
  const ext = path.extname(url);

  if (ext === '.wxss') {
    return {
      contents: fs.readFileSync(file, 'utf8'),
    };
  }

  return { file };
}

参考资料: