Rspack v0.6.0 发布,全新 Tree Shaking 算法

介绍

Rspack是一个基于 Rust 的高性能打包工具,由字节跳动 Web Infra 开源,可以被 Webpack 项目低成本集成,并提供 5~10 倍编译性能提升。

Rspack v0.6.0 版本现已发布!

  • ⭐️ 新版 Tree Shaking 算法 -> 更小的产物体积
  • ⭐️ 新增 CSS extract 插件,对齐 mini-css-extract-plugin
  • ⭐️ 新增 CSS modules 选项,对齐 webpack
  • ⭐️ 升级 SWC v0.90

主要功能更新

默认开启新版 Tree Shaking

Rspack 在早期支持了基本的 tree shaking 功能,由于最初的架构还未稳定, 我们使用了相对简单的方法,实现了基础版的 tree shaking(仅支持未使用导出删除)。

但是随着 Rspack 功能的完善,架构逐渐稳定,基础的 tree shaking 无法满足复杂的需求,比如:

  1. 无法处理循环引用,无法给其他构建阶段足够的优化信息,实现进一步的优化 (mangleExports, concatenateModules, barrel exports optimization)。

  2. 经常出现一些 interop 相关的 badcase,例如: worker-thread 模块,Common Js 模块,module federation 等。

为了解决以上问题,我们决定使用类似 webpack 的方案,自底向上重新实现整个优化流程,并在 0.4.2 引入 experiments.rspackFuture.newTreeshaking 配置,来实验性的开启新的优化算法。 经过 4 个月 bug 修复和优化,新的 tree shaking 算法已经相对稳定,我们决定在 v0.6 默认开启新的 tree shaking 算法。

新版算法支持了 reexports optimization(重导出优化),能够更精确地移除未使用的模块,这张图演示了重导出优化的过程:

import { Button } from 'antd' 为例,新版算法使产物体积从 159kB 下降到 129kB,提升约 20%。

更多细节请参考 Rspack - tree shaking 文档

内置支持 mini-css-extract-plugin

你现在可以使用 rspack.CssExtractRspackPlugin 作为 mini-css-extract-plugin 的替代。

这在一些复杂场景很实用,例如当内置的 CSS 处理无法满足你的需求、需要更定制化的 CSS module 选项等,或者你想要使用一些依赖 css-loader 的 loaders,但仍然想要将 CSS 提取成单独文件时。

详细配置见 CssExtractRspackPlugin

js 复制代码
const rspack = require('@rspack/core');

module.exports = {
  plugins: [new rspack.CssExtractRspackPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [rspack.CssExtractRspackPlugin.loader, 'css-loader'],
      },
    ],
  },
};

你可以在这里找到一个基础的项目例子。

不兼容更新

移除 experiments.rspackFuture.disableApplyEntryLazily

experiments.rspackFuture.disableApplyEntryLazily 选项自 v0.5.0 已被默认开启,并在 v0.6.0 中被删除。

移除 compiler.build 和 compiler.rebuild

compiler.buildcompiler.rebuild 不属于 Webpack 公开 API,目前已经被移除。

移除 builtins.css 并引入 CSS 相关 module.parser 和 module.generator 选项

移除 builtins.css,请使用引入的 CSS 相关的 module.parsermodule.generator 选项进行替代。

同时,从 v0.6.0 版本开始,Rspack 的 experiments css 将会以 webpack 的 experiments css 为目标进行对齐,这意味着和 webpack experiments css 一样在未来将不再支持不支持 CSS 变量的浏览器。因此,对于那些需要使用尚未得到 experiments css 支持的配置,或者需要兼容老版本浏览器的项目,我们推荐迁移至 rspack.CssExtractRspackPlugin

在 v0.6.0 中,我们引入了三种新的模块类型的 module.generatormodule.parser 选项:css/autocsscss/module,这些选项只有在启用 experiments.css 时才会生效,关于如何使用可查看这个例子

module.parser 选项中,csscss/autocss/module 模块类型都包含了 namedExports 属性。它取代了 builtins.css.namedExports 配置。

对于 module.generator 选项,css/autocss/module 模块类型提供了 exportsOnlyexportsConventionlocalIdentName 属性。css 类型只包含 exportsOnlyexportsConvention 属性。exportsOnlyexportsConventionlocalIdentName 分别取代了 builtins.css.modules.exportsOnlybuiltins.css.modules.localsConventionbuiltins.css.modules.localIdentName

除此之外,还包括一些关于默认值的修改:

  1. exportsConvention 的值从 'asIs', 'camelCaseOnly' 等变更为 'as-is', 'camel-case-only' 等,以保持与 webpack experiments css 的一致。

  2. namedExports: false 支持同时使用默认导出(default export)、命名导出(named export)和命名空间导出(namespace export),在此之前它只支持使用默认导出:

    js 复制代码
    // v0.6.0 之前只支持使用默认导出
    import classes from './index.module.css';
    
    // 现在除默认导出之外,也支持:
    // 命名空间导出
    import * as classes from './index.module.css';
    // 命名导出
    import { class1, class2 } from './index.module.css';
    // 默认导出和命名导出同时使用
    import classes, { class1, class2 } from './index.module.css';
  3. namedExports 的默认值从 false 变更为 true,这意味着你需要默认使用命名空间导入(例如 import * as classes from './style.css')或命名导入(例如 import { class1 } from './style.css'),这将提高与未来原生 CSS 模块的兼容性。而这并不意味着你需要一次性迁移所有的导入,你可以通过设置 namedExports: false 来禁用此行为,并且由于现在 namedExports: false 也支持命名导出和命名空间导出,因此你可以逐步迁移这些导入。

  4. localIdentName 的默认值在从在开发模式下 '[path][name][ext]__[local]' 和在生产模式下 '[hash]' 变更为在开发和生产模式下都是 '[uniqueName]-[id]-[local]',这将略微改善 CSS 产物的 gzip 压缩大小。

  5. exportsOnly 的默认值在 target: 'node' 下由原来的 false 变更为 true

  6. CSS 默认规则的模块类型从 css 变更为 css/autocss/auto 将自动解析以 .module..modules. 为中缀的 CSS 文件作为 CSS Modules 处理,这与 css-loadermodules.auto: true 行为一致,这将简化使用 less 或 sass 与 CSS Modules 的规则书写

升级 SWC 到 0.90.x

升级 Rust crate swc_core0.90.x,这会对使用 SWC Wasm 插件的用户产生影响。

当 CSS 的顺序在多个 chunk 中不一致时发出警告

当多个 chunk 中 css 顺序不一致时会发出警告,假如你有两个 entry,entryA 和 entryB,entryA 中引入 a.css 然后引入 b.css,而 entryB 中引入 b.css 然后引入 a.css。 当满足 splitChunks 条件时,a.css 和 b.css 会成为单独 chunk,这个 chunk 中 a.css 和 b.css 的顺序无法保证,会产生如下的警告

txt 复制代码
WARNING in ⚠ chunk src_a_css-src_b_-5c8c53 [css-extract-rspack-plugin]
  │ Conflicting order. Following module has been added:
  │  * css ./css-loader/dist/cjs.js??ruleSet[1].rules[2].use[1]!./src/a.css
  │ despite it was not able to fulfill desired ordering with these modules:
  │  * css ./css-loader/dist/cjs.js??ruleSet[1].rules[2].use[1]!./src/b.css
  │   - couldn't fulfill desired order of chunk group(s) parent2
  │   - while fulfilling desired order of chunk group(s) parent1

如果你确定他们的顺序不一致没有关系,可以通过配置 ignoreWarnings 来忽略这种错误。

js 复制代码
module.exports = {
  ignoreWarnings: [/Conflicting order/],
};

迁移指南

使用 rspack.CssExtractRspackPlugin

如果你曾经使用 Webpack 和 mini-css-extract-plugin,只需要将 mini-css-extract-plugin 换成 rspack.CssExtractPlugin 即可。

diff 复制代码
+ const CssExtract = require('@rspack/core').CssExtractRspackPlugin;
- const CssExtract = require('mini-css-extract-plugin');
module.exports = {
  plugins: [new CssExtract()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [CssExtract.loader, 'css-loader'],
      },
    ],
  },
};

迁移 builtins.css 配置

  1. 使用 module.parser["css/auto"].namedExports 替代 builtins.css.namedExports
  2. 使用 module.generator["css/auto"].exportsOnly 替代 builtins.css.modules.exportsOnly
  3. 使用 module.generator["css/auto"].exportsConvention 替代 builtins.css.modules.localsConvention
  4. 使用 module.generator["css/auto"].localIdentName 替代 builtins.css.modules.localIdentName

以上出现的 "css/auto" 为 CSS 默认的模块类型,可根据需要修改为 "css""css/module"

添加以下配置将保持原有 builtins.css 默认行为,可根据以下配置根据需要进行修改:

diff 复制代码
module.exports = {
   // ...
+  module: {
+    generator: {
+      "css/auto": {
+        exportsOnly: false,
+        exportsConvention: 'as-is',
+        localIdentName: isProduction ? '[hash]' : '[path][name][ext]__[local]',
+      },
+      "css": {
+        exportsOnly: false,
+        exportsConvention: 'as-is',
+      },
+      "css/module": {
+        exportsOnly: false,
+        exportsConvention: 'as-is',
+        localIdentName: isProduction ? '[hash]' : '[path][name][ext]__[local]',
+      },
+    },
+    parser: {
+      "css/auto": {
+        namedExport: false,
+      },
+      "css": {
+        namedExport: false,
+      },
+      "css/module": {
+        namedExport: false,
+      },
+    },
+  },
}

如需要对部分模块进行配置,可使用 module.rules 中的 rule.parserrule.generator 选项进行配置。

调用 compiler.run 执行构建

compiler.buildcompiler.rebuild 已经被废弃,请切换到 compiler.run 进行构建,与重新构建。

升级 SWC 插件

0.6.0 中,Rust crate swc_core 的版本升级到 0.90.x,使用到的 swc wasm 插件需要确保其使用的 swc_core 的版本一致性,否则可能产生无法预知的问题。

详情请参考文档

相关推荐
梦境之冢34 分钟前
axios 常见的content-type、responseType有哪些?
前端·javascript·http
racerun37 分钟前
vue VueResource & axios
前端·javascript·vue.js
J总裁的小芒果1 小时前
THREE.js 入门(六) 纹理、uv坐标
开发语言·javascript·uv
m0_548514771 小时前
前端Pako.js 压缩解压库 与 Java 的 zlib 压缩与解压 的互通实现
java·前端·javascript
AndrewPerfect1 小时前
xss csrf怎么预防?
前端·xss·csrf
Calm5501 小时前
Vue3:uv-upload图片上传
前端·vue.js
浮游本尊1 小时前
Nginx配置:如何在一个域名下运行两个网站
前端·javascript
m0_748239831 小时前
前端bug调试
前端·bug
m0_748232921 小时前
[项目][boost搜索引擎#4] cpp-httplib使用 log.hpp 前端 测试及总结
前端·搜索引擎
新中地GIS开发老师1 小时前
《Vue进阶教程》(12)ref的实现详细教程
前端·javascript·vue.js·arcgis·前端框架·地理信息科学·地信