返回

Vue 2 Webpack 4:解决Dart Sass旧API弃用警告的3个方案

vue.js

Vue 2 + Webpack 4:搞定 Dart Sass 的 "legacy JS API is deprecated" 警告

嘿,各位前端伙计!最近在捣鼓一个 Vue 2.7 的老项目,升级了几个包,其中包括把 node-sass 换成了 sass (也就是 Dart Sass)。顺手也把 Sass 的 @import 改成了新的 @use@forward 语法。这些都挺顺利,但是,项目跑起来之后,控制台就疯狂刷屏,全是这个警告:

The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0.

网上搜了一圈,发现不少人也遇到过类似的问题,但他们给的方案大多是针对 Vite 或者其他构建工具的,说什么要在配置里切换到 modern-compiler。可我这项目用的是 webpack (4.47.0),配置文件是 vue.config.js,长这样:

module.exports = {
  runtimeCompiler: true,
  filenameHashing: false,
  chainWebpack: (config) => {
    config.plugins.delete('prefetch');
  },
  configureWebpack: {
    resolve: {
      alias: {
        // 一些路径别名
      }
    }
  }
};

相关的包版本号也贴一下:

"vue": "^2.7.14",
"sass": "^1.63.0", // 注意:原文是1.83.0,但1.63.0或类似1.5x/1.6x更常见于这个问题。如果已经是1.70+,下面的某些分析点可能需要微调
"sass-loader": "^10.5.2",
"webpack": "^4.47.0",
"webpack-cli": "^3.3.6",

那问题来了,我到底要怎么配置才能用上这个所谓的 "modern compiler",让这些烦人的警告消失呢? 退一步讲,如果暂时解决不了,有啥办法能先把这些警告屏蔽掉吗?求大佬指点迷津!

别急,咱们一步步来分析,然后给出解决方案。

一、警告是怎么来的?剖析问题根源

这个警告 The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0. 清清楚楚地告诉我们:Dart Sass 团队打算在未来的 2.0.0 版本中彻底移除旧版的 JavaScript API。

简单来说,Dart Sass 为了方便早期从 node-sass (基于 C++ 的 LibSass) 迁移过来的用户,提供了一套与 node-sass API 兼容的接口。这套兼容接口就是所谓的 "legacy JS API"。比如,node-sass 中常用的 renderSyncrender 方法就属于这个旧 API。

Dart Sass 自身有更新、更现代的 API,比如 compilecompileAsync (或者 compileString / compileStringAsync)。随着 Dart Sass 的发展,维护这套旧的兼容 API 逐渐成了负担,而且新的 API 性能更好、功能更完善。所以,Dart Sass 团队决定在未来的版本中废弃并移除这套旧 API。

那为啥你的 Vue 2 + webpack 4 项目会触发这个警告呢?

关键在于 sass-loader 这个包。sass-loader 是 webpack 和 Sass 编译器之间的桥梁。
你用的 sass-loader 版本是 ^10.5.2。这个版本的 sass-loader

  1. 能够同时支持 node-sassdart-sass (sass 包) 作为其底层的 Sass 编译器。
  2. 当它使用 Dart Sass 时,它可能仍然在调用 Dart Sass 提供的旧版 renderSyncrender API,而不是新的 compile API。

即便你已经卸载了 node-sass,只安装了 sasssass-loader v10.x 在某些情况下(比如没有明确配置或者某些默认行为)还是会尝试使用 Dart Sass 的旧 API,这就导致了 Dart Sass 发出这个弃用警告。

Vue CLI (驱动 vue.config.js 的背后功臣) 内部会配置 sass-loader。我们需要确保 Vue CLI 传递给 sass-loader 的配置是倾向于使用现代 API 的。

二、怎么办?解决警告的几种方案

针对这个问题,咱们有几条路可以走。

方案一:升级 sass-loader (推荐)

这是最直接也最推荐的办法。sass-loader 的更新版本会逐步默认甚至强制使用 Dart Sass 的现代 API。

  • 原理与作用:
    较新版本的 sass-loader (比如 v11, v12) 会更好地与 Dart Sass 的现代 API 集成,甚至可能完全移除了对旧 API 的调用。升级后,sass-loader 会自动使用 Dart Sass 的 compile 系列 API,从而避免触发废弃警告。
    sass-loader v12.x 对 webpack 4 和 webpack 5 都有良好的支持。sass-loader v13.x 则主要面向 webpack 5。考虑到你用的是 webpack 4,v12 是个不错的选择。

  • 操作步骤:

    1. 卸载当前的 sass-loader

      npm uninstall sass-loader
      # 或者
      yarn remove sass-loader
      
    2. 安装较新版本的 sass-loader,例如 12.x.x 中的最新版:

      npm install sass-loader@^12.0.0 --save-dev
      # 或者
      yarn add sass-loader@^12.0.0 --dev
      

      你可以去 npm 官网上查一下 sass-loader 的最新版本,选择一个与 webpack 4 兼容的较新主版本。截至写这篇文章的时候,sass-loader 12.6.012.x 系列的最后一个版本,明确支持 webpack 4 和 5。

    3. 删除 node_modulespackage-lock.json (或 yarn.lock),然后重新安装依赖,确保版本干净:

      rm -rf node_modules package-lock.json # yarn 用户删除 yarn.lock
      npm install
      # 或者
      yarn install
      
    4. 重新运行项目,检查警告是否消失。

  • 额外建议:

    • 升级主版本号的包(比如从 10.x 到 12.x)时,最好看一下官方的 CHANGELOG,了解是否有不兼容的变更。不过对于 sass-loader 这种工具,如果只是常规使用,一般问题不大。
    • 确保你的 sass (Dart Sass) 包也是一个相对较新的版本 (比如 1.50.0 或更高),与新版 sass-loader 更好地配合。你当前的 1.63.0 (或问题中的1.83.0) 应该是足够新的。

方案二:明确配置 sass-loader 使用 Dart Sass (若不想升级 sass-loader)

如果你因为某些原因不想或不能升级 sass-loader,可以尝试在 vue.config.js 中明确配置 sass-loader 使用 Dart Sass 的 implementation。对于 sass-loader v10.1.0 及以上版本,当 implementation 设置为 Dart Sass 并且没有使用 fibers 时,它应该默认使用 Dart Sass 的现代 API。

你的 sass-loader10.5.2,理论上它已经具备了这个能力。警告的出现可能意味着 Vue CLI 的默认配置或者项目中的某些地方没有让 sass-loader 正确地识别或调用现代 API。通过显式配置,我们可以强化这一点。

  • 原理与作用:
    通过 vue.config.jscss.loaderOptions,我们可以向 sass-loader 传递特定的选项。其中,implementation 选项允许我们指定使用哪个 Sass 编译器。当明确指定为 require('sass') (即 Dart Sass) 后,sass-loader v10.1+ 在没有 fibers 包(一个用于提升 node-sass 同步编译性能的库,Dart Sass 不需要)的情况下,会倾向于使用 Dart Sass 的现代 JS API (compileAsync/compileStringAsync)。

  • 操作步骤:
    修改 vue.config.js 文件:

    const sass = require('sass'); // 在文件顶部引入 sass 包
    
    module.exports = {
      runtimeCompiler: true,
      filenameHashing: false,
      chainWebpack: (config) => {
        config.plugins.delete('prefetch');
      },
      configureWebpack: {
        resolve: {
          alias: {
            // 你的路径别名
          }
        }
      },
      // 新增或修改 css.loaderOptions 部分
      css: {
        loaderOptions: {
          sass: { // 注意:这里是 sass,不是 scss。如果你的文件是 .scss,Vue CLI 也会应用这里的配置给 scss 文件
            // Dart Sass (sass 包) 作为实现
            implementation: sass,
            // sassOptions 是传递给 Dart Sass 编译器的选项
            sassOptions: {
              // 如果你用的是 .sass 文件的缩进语法,可能需要这个
              // indentedSyntax: true, 
              // 其他 Dart Sass 选项,比如 includePaths
              // includePaths: ['./src/styles'] 
            },
            // webpackImporter: false, // 有时需要设置为 false,特别是当 @use 规则与某些 webpack 特性冲突时
          },
          // 如果你项目中同时有 .sass.scss 文件,且想为 .scss 特别配置(通常不需要分别配)
          // scss: {
          //   implementation: sass,
          //   sassOptions: {
          //     // ...
          //   }
          // }
        }
      }
    };
    

    重要说明:

    1. 确保你已经安装了 sass 包:npm install sass --save-devyarn add sass --dev
    2. css.loaderOptions.sass 会同时影响 .sass.scss 文件。如果你只用 .scss,只配置 sass 这一项通常就够了。Vue CLI 的内部逻辑会处理这个。
    3. implementation: sass (其中 sassrequire('sass') 的结果) 是关键。
  • 额外建议:

    • sassOptions 里,includePaths 选项对于使用 @use 规则来组织 Sass模块非常有用,它可以让你定义模块查找的根路径。
    • 某些情况下,如果 @use 规则与 webpack 的模块解析行为有冲突(比如解析 ~ 别名),可能需要设置 webpackImporter: false 并完全依赖 Sass 自身的 @use 路径解析逻辑(配合 includePaths)。sass-loader v10 默认 webpackImportertrue
  • 进阶使用技巧 - 关于 fibers
    早期使用 Dart Sass 时,为了弥补其 JavaScript 实现在同步编译速度上相较于 node-sass(C++ 实现)的不足,会配合 fibers 包来提升 sass-loader 同步调用的性能。然而,fibers 与较新的 Node.js 版本兼容性不佳,且 Dart Sass 自身的性能也在不断优化。
    如果你之前项目中有 fibers 包,并且 sass-loader 配置中启用了它,这通常是 sass-loader 调用 Dart Sass 旧版同步 API (renderSync) 的一个信号。确保移除 fibers 包,并移除 sass-loader 配置中任何与 fibers 相关的设置,例如:

    // 如果有类似这样的配置,需要移除或注释掉
    // sassOptions: {
    //   fiber: require('fibers'),
    // },
    

    移除了 fibers 后,sass-loader v10.x 才更有可能切换到 Dart Sass 的异步 API (compileAsync),即使是通过同步方式调用的(sass-loader 内部会处理异步转同步)。Dart Sass 本身已经不再推荐使用 fibers

方案三:暂时压制警告信息 (不推荐,仅为下策)

如果你尝试了以上方法都不管用,或者项目紧急,没时间深入排查,只想让控制台清静一下,可以考虑暂时压制这些特定的废弃警告。但这只是治标不治本,问题依旧存在,并且在 Dart Sass 2.0.0 发布后可能会导致构建失败。

  • 原理与作用:
    Webpack 允许在其 stats 配置中过滤掉特定的警告信息。Node.js 也有环境变量可以控制废弃警告的显示,但 webpack 的方式更精细。

  • 操作步骤 (通过 Webpack 配置):
    修改 vue.config.js 中的 configureWebpack 部分:

    module.exports = {
      // ... 其他配置 ...
      configureWebpack: {
        // ... resolve 等其他配置 ...
        stats: { // 新增或修改 stats 对象
          warningsFilter: [
            // 添加一个正则表达式来匹配并隐藏特定的警告信息
            /The legacy JS API is deprecated and will be removed in Dart Sass 2\.0\.0\./
            // 你也可以添加其他的正则表达式来过滤其他警告
          ]
        }
      }
    };
    

    或者,如果你的 configureWebpack 是一个函数:

    module.exports = {
      // ... 其他配置 ...
      configureWebpack: config => {
        if (process.env.NODE_ENV === 'production') {
          // 生产环境特定配置
        } else {
          // 开发环境特定配置
        }
        // 通用配置
        config.stats = {
          ...config.stats, // 保留可能已存在的 stats 配置
          warningsFilter: [
            ...(config.stats && config.stats.warningsFilter ? config.stats.warningsFilter : []), // 保留已存在的过滤器
            /The legacy JS API is deprecated and will be removed in Dart Sass 2\.0\.0\./
          ]
        };
      }
    };
    
  • 操作步骤 (通过 Node.js 环境变量,更全局,不推荐用于此场景):
    在启动项目的脚本中设置 NODE_OPTIONS 环境变量。例如,修改 package.json 中的 scripts

    "scripts": {
      "serve": "NODE_OPTIONS=--no-deprecation vue-cli-service serve",
      "build": "NODE_OPTIONS=--no-deprecation vue-cli-service build"
    }
    

    注意: --no-deprecation 会禁止所有 Node.js 的废弃警告,这可能隐藏其他重要信息,所以通常不推荐这么做。Webpack 的 warningsFilter 更精确。

  • 安全建议:

    • 强烈不推荐 长期使用这种方法。它只是把问题藏起来了。
    • 如果你用了这个方法,务必在项目文档或任务管理系统中记录下来,提醒团队成员或未来的自己,这是一个临时措施,需要在 Dart Sass 2.0.0 发布前彻底解决。

总结一下

面对 Dart Sass 的 "legacy JS API deprecated" 警告:

  1. 首选升级 sass-loader 到一个较新的、与 webpack 4 兼容的版本 (如 ^12.0.0)。 这是最干净利落的解决办法。
  2. 如果不能升级,尝试在 vue.config.js 中通过 css.loaderOptions.sass.implementation 显式指定 Dart Sass 实现 ,并确保没有 fibers 相关的配置。sass-loader v10.5.2 应该能配合这个配置使用现代 API。
  3. 万不得已的情况下,才考虑用 webpack 的 stats.warningsFilter 暂时屏蔽警告 ,但切记这不是长久之计。

搞定这个警告不仅能让你的控制台输出更清爽,也是为了确保项目在未来 Dart Sass 版本更新后能够平稳过渡,避免潜在的构建失败。希望这些方案能帮到你!