Rspack 是由 ByteDance Web Infra 团队孵化的基于 Rust 语言开发的 Bundler,拥有高性能、兼容 Webpack 生态、定制性强等多种优点,它解决了我们在业务场景中遇到的非常多的问题,让很多开发者的体验有了质的提升。
文章来源|Rspack 开源社区
Rspack v0.7 版本已经正式发布!
这是 Rspack v1.0 版本发布前的最后一个 minor 版本,此后 Rspack 团队将投入到 v1.0 版本的开发中,并致力于尽快推出 Rspack v1.0 alpha 版本。
在 Rspack v0.7 中,值得关注的变更如下:
-
支持 Lazy Compilation :通过按需编译,显著提升大型应用的 dev startup 性能。
-
更快的 CSS 构建 :引入全新的 css-module-lexer,使 CSS 打包速度提升 4 倍。
-
不兼容更新 :移除一些不稳定的 API,使默认行为与 webpack 更加一致。
0 1
支持 Lazy Compilation
Rspack v0.7 支持了 lazy compilation(懒编译),它对于提高多入口应用(MPA)或大型单页面应用(SPA)的 dev 启动性能非常有帮助。
什么是 Lazy Compilation
Lazy compilation 是一个提升启动性能的良好手段,它可以按需编译模块,而不是在启动时就编译所有模块。这意味着开发者在启动 dev server 时,可以很快看到应用运行,并分次构建所需的模块。
为什么需要 Lazy Compilation
尽管 Rspack 本身具备良好的性能,但是面对具有大量模块的应用,其整体构建时间仍然可能不够理想。这是因为应用中的模块需要经过不同 loader 的编译,包括
postcss-loader
、
sass-loader
、
vue-loader
等,它们都会产生额外的编译开销。
在启用 lazy compilation 的情况下,Rspack 仅会编译被请求的「页面入口」和「动态 import 模块」,这可以显著减少开发启动时编译的模块数量,从而提升启动时间。
想象下面的场景:
你的团队在开发一个包含几十个页面的 MPA 应用,大部分时候,你只参与开发其中的某几个页面,并不需要构建其他页面的代码。此时,你可以启用 lazy compilation,使 Rspack 仅编译你访问的页面所引用的模块。
在开启 lazy compilation 后,Rspack 会将「页面入口」和「dynamic import」作为分割点,例如:
if (someCondition) {
import('./b.js');
}
当我们编译 a.js 时,Rspack 会将 b.js 当成一个空模块,假装用户从未在其中编写过任何代码。一旦我们需要访问 b.js,Rspack 就用其原始内容填充 b.js 模块,有点类似于用户瞬间编写了这部分代码。
以 Rspack 文档站为例,它包含多个页面,当开启 lazy compilation 后,只有访问到的入口及其依赖的模块会被构建,这极大的提升了启动速度,启动时间从 2.1s 降至 0.05s。
当开发者访问网站的某一个页面时,会触发该页面的构建,且这次构建的时间依然会明显小于完整的构建时间。
如何使用
现在,你可以通过 experiments.lazyCompilation 配置项来开启懒编译功能:
const isDev = process.env.NODE_ENV === 'development';
module.exports = {
experiments: {
lazyCompilation: isDev,
},
};
注意,当前 lazy compilation 是对齐 webpack 实现的, 并且仍处于实验性阶段 。在部分场景下,lazy compilation 可能无法按照预期工作,或是性能提升不明显。
我们将持续完善 lazy compilation 在不同场景下的可用性,使之达到更稳定的状态。如果你在使用过程中遇到任何问题,欢迎通过 GitHub Issues 向我们反馈。
GitHub Issues: https://github.com/web-infra-dev/rspack/issues
02
更快的 CSS 构建
在 v0.7 版本中,我们对 experiments.css 的内部实现进行了重构。
针对 CSS 依赖分析,我们使用 Rust 开发了 css-module-lexer ,这是一个针对 CSS Modules 的高性能 lexer,能够解析 CSS 或 CSS Modules 并返回其依赖元信息。
在接入 css-module-lexer 后,Rspack 能够支持更复杂的 CSS Modules 语法,对齐了 webpack 的 css-loader 的行为。比如能够支持以下 CSS Modules 语法:
:local(.parent):global(.child) > ul {
color: red;
}
下图是重构前后的 CSS 解析流程示意:
同时, css-module-lexer 也给 Rspack 的 experiments.css 带来了显著的性能提升。经过性能测试, bootstrap.css 打包速度提升约 4 倍:
-
重构前:约 84ms(分析 CSS 依赖约 71ms)
-
重构后:约 25ms(分析 CSS 依赖约 11ms)
03
不兼容更新
Rspack 会在 1.0 版本前,逐步下线所有不稳定的 API 和配置,更多配置 / API / 默认行为将与 webpack 保持一致。
移除一些不稳定的 JavaScript API
Rspack 初期暴露了一些预期仅供内部使用且不稳定的 API,如 compiler.compilation 和 compiler.builtinPlugins 等,这些 API 并不稳定且无法在 webpack 中使用。
在 v0.7 版本中,我们重新整理了目前暴露的 API 及其接口定义。如果你有使用到这些 API,你需要进行一些调整,切换到与 webpack 一致的实现方式。
以下 API 已废弃:
- compiler.builtinPlugins
- compiler.compilation
- compiler.compilationParams
- compiler.getAsset(name)
- statsError.formatted
- statsWarning.formatted
- ...
关于废弃 API 的详细情况可参考 rspack#6448 、 rspack#6505 。
CSS @import 规则须先于其他规则
0.7 版本我们对 experiments.css 的内部实现进行了部分重构。
重构后,当 @import 不在最顶部时,会得到如下报错,此时需要你手动将 @import 规则调整到顶部。
ERROR in ./src/main.css
× Module parse failed:
╰─▶ × CSS parsing warning: Any '@import' rules must precede all other rules
╭─[4:1]
4 │ };
5 │
6 │ @import 'bootstrap/dist/css/bootstrap.css';
· ───────
7 │
8 │
╰────
help:
You may need an appropriate loader to handle this file type.
移除 builtins 以及 experiments.rspackFuture.newTreeshaking
v0.7 已移除 builtins.treeShaking (oldTreeShaking) 和 experiments.rspackFuture.newTreeshaking (新 tree shaking 开关) 配置,将旧的 tree shaking 功能彻底下线。
移除 resolve.browserField
该配置为 resolve.aliasFields = ["browser"] 的简写,由于 Rspack 已经支持 resolve.aliasFields ,所以不再需要该配置。
移除 experiments.newSplitChunks
该配置用于开启新的 splitChunks 实现,由于 Rspack 已经默认使用新的 splitChunks 实现,所以不再需要该配置。
移除 snapshot
该配置用于配置 cache snapshot 的行为。在 Rspack 目前的增量架构下,cache 不再依赖 snapshot,所以不再需要该配置。
移除 generator.css.exportsConvention
该配置用于控制 experiments.css 的 CSS 模块导出的命名形式,仅对于模块类型为 css/module 的模块才会有导出,对于模块类型为 css 的模块并不存在导出,所以不需要该配置。
升级 SWC 到 0.91.x
升级 Rust crate swc_core 到 0.91.x ,这会对使用 SWC Wasm 插件的用户产生影响。
04
迁移指南
升级 SWC 插件
在 v0.7 中,Rust crate swc_core 的版本升级到 0.91.x ,使用到的 SWC Wasm 插件需要确保其使用的 swc_core 的版本一致性,否则可能产生无法预知的问题。
详情请参考 文档 。
文档地址: https://swc.rs/docs/plugin/selecting-swc-core#091x
替换 resolve.browserField 为 resolve.aliasFields
如果你之前配置了 resolve.browserField ,则需要使用 resolve.aliasFields 进行替换:
-
resolve.browserField = true 替换为 resolve.aliasFields = ["browser"]
-
resolve.browserField = false 替换为 resolve.aliasFields = []
移除 generator.css.exportsConvention
如果你之前配置了 module.generator.css.exportsConvention 或在 module.rule 中配置了 generator.exportsConvention ,只需要删除该配置即可。
05
Rsbuild v0.7
Rsbuild v0.7 已与 Rspack v0.7 同步发布,请阅读 Rsbuild v0.7 发布 了解更多。
Rsbuild v0.7 发布地址: https://rsbuild.dev/zh/community/releases/v0-7