跳至主要內容

Rspack

njr工程化项目打包rspack大约 5 分钟约 1615 字

Why Rspack?

面对大型项目,开发和生产环境的构建需要耗费很长时间。

组内实际项目在生产环境中构建需要接近 30 分钟。

按照官方说法,Rspack 拥有:

  • 快速的 Dev 启动性能
  • 高效的 Build 性能
  • 灵活的配置
  • 生产环境的优化能力

Rspack 创建项目

使用 Rspack CLI:

pnpm create rspack@latest

目前支持三种模版:

  • react
  • react-ts
  • vue

用该命令创建的项目 Rspack 不是最新,因此选择从零开始。 (11 月 29 日 已适配为最新版本。)

从零开始

安装相关依赖。

pnpm init
pnpm install react react-dom
pnpm install -D typescript @types/react @types/react-dom
pnpm install -D @rspack/cli @rspack/core

为了快速启动项目,直接将所有文件内容复制,然后启动项目,报错:

报错
报错

从官网中查看 迁移示例open in new window,并未得到有用信息。复制错误信息 JavaScript parsing error 搜索 issue。

issue 官网示例报错open in new window 中找到解决方法:

这里按照官方解答无效,查看 rspack-template 最新配置如下:

{
	test: /\.(jsx?|tsx?)$/,
	use: [
		{
			loader: "builtin:swc-loader",
			options: {
				sourceMap: true,
				jsc: {
					parser: {
						syntax: "typescript",
						tsx: true
					},
					transform: {
						react: {
							runtime: "automatic",
							development: isDev,
							refresh: isDev
						}
					}
				},
				env: {
					targets: [
						"chrome >= 87",
						"edge >= 88",
						"firefox >= 78",
						"safari >= 14"
					]
				}
			}
		}
	]
}

Rspack VS Webpack

常见语言与资源模块支持对比如下:

语言/资源支持(Rspack/Webpack)
CSS"style-loader", "css-loader"
PostCSS"postcss-loader", "style-loader", "css-loader", "postcss-loader"
Less"less-loader", "style-loader", "css-loader", "postcss-loader", "less-loader"
Sass"sass-loader", "style-loader", "css-loader", "postcss-loader", "sass-loader"
图片type: "asset", type: "asset"
TS内置 SWC, "ts-loader" or "babel-loader"
JSX/TSX"babel-loader", "presets": ["@babel/preset-react", "@babel/preset-typescript"]

阅读 - Bundler 的设计取舍

原文地址:Bundler 的设计取舍open in new window

Why We Build Rspack

原文

性能始终是 Webpack 绕不开的话题,虽然我们尝试了各种 Webpack 的优化方式,如 swc-loader、esbuild-loader、thread-loader、cache-loader、MFSU、Persistent Cache 等等。

但是最终就是这些方案虽然可能缓解一部分的性能问题,面对大型项目仍然捉襟见肘,另一方面这些方案导致构建过程更加黑盒化。

如 Persistent Cache 依赖业务配置良好的 build dependencies,esbuild-loader 不支持 es5 的降级,cache-loader 忘记清理 cache 导致产物没更新。

优化方式优点缺点
swc-loaderSWC 是一个用 Rust 编写的超快的 JavaScript/TypeScript 编译器。swc-loader 使 Webpack 可用 SWC 作为编译器,取代 Babel。在处理老版本(如 ES5)的 JavaScript 语法兼容性问题时,可能表现不如 Babel.
esbuild-loaderesbuild 是一个 JavaScript 打包器和压缩器,速度极快。esbuild-loader 同样替代 Babel,性能提升更大。同上
thread-loaderthread-loader 允许 Webpack 使用多线程加载和编译,提升构建速度。可能会增加硬件资源(如 CPU 和内存)的使用。对于资源受限的环境(如某些 CI/CD 环境或者低端硬件),可能导致构建失败。
cache-loadercache-loader 缓存其他 loader 的执行结果。当源文件没有变化时,Webpack 可以直接使用缓存的结果,避免重复工作。忘记清理 cache 导致产物没更新
MFSU对于不常改变的模块,通过 MFSU 可以预编译并复用它们,缩短构建时间。如果模块数量较大或模块本身较大,预编译所需的时间可能较长,甚至可能导致构建速度下降而非提升。此外,这种优化可能使得代码的调试更为困难。
Persistent Cache从 Webpack 5 开始,提供了持久化缓存特性。它会在硬盘上保存一些构建信息,对于经常进行的构建任务,来自持久化缓存的信息可使构建速度快很多。如果业务的构建依赖项配置不恰当,Persistent Cache 有可能导致产物与预期不一致,使得构建过程更加“黑盒化”。

原文

Rollup 的产物优化能力相比弱了不少,尤其是缺失 Bundle Splitting 等能力导致业务很难做精细的优化,因此内部有不少业务是 dev 下运行 Vite,生产环境用 Webpack,这导致开发和生产存在着较大的差异。

「产物优化能力」通常指的是一种工具在构建后产生的代码中应用优化的能力。这类优化可以包括 代码压缩(移除无用的代码或者空格、注释)、代码拆分(将大的代码块拆分为多个较小的模块,以实现并行加载或延迟加载)、抽取公共的模块(例如将多次使用的库抽取出来,避免重复打包)、树摇(剔除项目中未引用的代码)等等。

由于 Rollup 设计之初主要为库作者服务,其支持的一些功能可能没有 Webpack 那么强大。比如,Webpack 提供了非常强大的代码分割(code splitting)和长缓存优化(long term caching optimisation)功能,即你提到的 Bundle Splitting 能力。这些功能对于构建大型、复杂的应用程序非常有用。

Vite 使用 Rollup 作为生产环境构建工具,它非常适合于小型到中型项目,因为它速度快。但当你面对一个大型项目,可能需要用到更高级的优化手段时,Webpack 可能会是更好的选择。

How We Build Rspack

原文

最终导致转向了 Webpack 架构。

一等公民

Rollup 则是只有 Javascript 才是一等公民,而 Webpack 5 支持了更多的一等公民模块。

插件 API 设计

插件设计对比:

插件机制RollupWebpack
模块转换
过滤器(filter):即过滤哪些模块进行转换。
转换器(transformer): 即对过滤模块进行怎样的转换。
模块类型转换(change module type): 即我们可能需要将一个模块从 A 类型转换成 B 类型。
三个维度揉进了一个 transform hook 里:
- 高频的 callback 通信
- 用户灵活性的丧失
- 丧失了模块转换逻辑的组合性
过滤器:rule.test
转换器:@svgr/webpack loader
类型转换:inlineMatchResource
AST 复用--

Beyond Webpack

使用 Rust 来实现一套 Webpack 架构(最好能复用 Webpack 生态的插件/loader)的、同时又通过自定义一些具体实现(例如缓存和 swc)来提升构建效率的工具。