从 5.6s 到 1.4s,从 192 个依赖砍到 1 个,Rspack 2.0 不只是"更快的 webpack"了。
Rspack 2.0 在 7 月 29 日正式发布。不只是"字节跳动的 webpack 替代品"。
这次 2.0 的核心变化可以浓缩成三句话:
- 性能翻倍------相比 1.0,构建速度最多快 100%,10000 组件项目缓存构建从 5.6s 降到 1.4s
- 依赖瘦身 ------
@rspack/dev-server依赖从 192 个砍到 1 个,安装体积减少 90%+ - 全面 ESM 化------核心包转为纯 ESM,支持 RSC、import defer 等现代特性
总结就一句它不再满足于只做"更快的 webpack",开始走自己的路了。
1. Rspack 2.0 到底更新了什么?
1.1 性能提升
先看一组最直观的基准测试数据(来源:rspack-react-10k-benchmark,测试环境:M3 Pro 芯片、32GB 内存、NVMe SSD、Node.js 22.12):
| 版本 | 生产构建(无缓存) | 生产构建(有缓存) | HMR 热更新 |
|---|---|---|---|
| Rspack 1.0 | 5.6s | 5.6s | 128ms |
| Rspack 1.7 | 3.6s | 2.2s | 134ms |
| Rspack 2.0 | 3.1s | 1.4s | 118ms |

简单来说:启用持久化缓存后,10000 个组件的 React 项目,生产构建只要 1.4 秒。
这些数字都传递了什么信息呢?未做深度性能优化、未开启持久化缓存的原生 webpack 5,同规模项目生产构建通常在 30-60 秒量级。Rspack 2.0 无缓存首次构建约为 webpack 的 10-20 倍,持久化缓存命中场景约为 webpack 缓存构建的 20 倍以上。
除了构建速度,2.0 还在缓存场景做了两个优化:
- SWC 压缩器的压缩结果可以缓存复用,命中缓存时构建性能再提升约 50%
- 启用缓存后内存占用下降了 20%+
同项目在 webpack 5 下的生产构建时间约为 35-45 秒(首次)/ 28-35 秒(缓存命中)。Rspack 2.0 缓存构建 1.4 秒约为 webpack 缓存构建的 20-25 倍。
CI 环境的缓存陷阱 :持久化缓存依赖 package-lock.json 和环境变量来生成缓存 key。如果 CI 构建每次都是全新环境且未持久化 node_modules/.cache 目录,缓存命中率几乎为零,反而会因磁盘读写拖慢构建。建议通过 CI 缓存能力持久化缓存目录,或固定 RSPACK_CONFIG_CACHE_KEY 环境变量提升命中率。
1.2 依赖大瘦身:从 192 到 1
这个变化在 Hacker News 上反而比性能数据更火。
| 包 | 1.x 依赖数 | 2.0 依赖数 | 安装体积 |
|---|---|---|---|
@rspack/dev-server |
192 | 1 | 15MB → 1.4MB |
@rspack/core |
8 | 1 | --- |
@rspack/cli |
--- | 0(零依赖) | --- |

它是怎么做到的呢?
- 用
connect-next替代 Express------开发服务器的中间件模型用 Connect 就够了,不需要完整的 Express - 依赖打包进发布产物 ------把非核心依赖直接打包进 npm 包,由 Rspack 统一控制版本,避免供应链风险。不过是两面性的:这种「vendor 化」策略意味着你无法通过
npm overrides直接升级传递依赖版本来修复 CVE 漏洞,需依赖官方发版;patch-package虽可对打包后的产物生效,但维护成本极高,不推荐企业级项目使用。大型企业需要评估内部安全扫描策略是否兼容这种方式 - 用 Node.js 20+ 原生 API ------比如用内置的
styleText替代picocolors - 非核心依赖改为可选 ------比如
@module-federation/runtime-tools只在使用模块联邦插件时才需要手动安装
有位评论者说得挺好:与性能数据相比,依赖项减少的数字更让我印象深刻------这是一种理念的转变,而不仅仅是基准测试。
1.3 纯 ESM 核心
Rspack 2.0 的核心包(@rspack/core、@rspack/cli、@rspack/dev-server、@rspack/plugin-react-refresh)全部转为纯 ESM 包发布,移除了 CommonJS 构建产物。
那么问题来了,我的现有项目还在用 CommonJS,会不会挂?
答案是在 Node.js 版本符合要求且未引入含顶层 await 的 ESM 依赖的前提下,大概率不会。Node.js 22.12+ 已稳定支持 CommonJS 中通过 require() 加载 ESM 模块(require(esm)),20.19+ 为实验性支持。因此大多数通过 JavaScript API 使用 Rspack 的项目无需修改代码。
但有一点需要注意:如果 ESM 模块内部使用了顶层 await(Top-level await) ,require() 会直接抛出 ERR_REQUIRE_ASYNC_MODULE 错误,没法绕过。目前 Rspack 2.0 自身没有使用顶层 await,但如果你在配置文件中引入了含顶层 await 的第三方 ESM 依赖,CJS 项目就会挂:
示例:
js
// ❌ 会报错:CJS 配置文件引入了含顶层 await 的 ESM 依赖
// rspack.config.js (CommonJS)
const someEsmPkg = require('some-esm-pkg-with-tla'); // 抛出 ERR_REQUIRE_ASYNC_MODULE
// ✅ 修复方案1:将配置文件改为 rspack.config.mjs
import someEsmPkg from 'some-esm-pkg-with-tla';
// ✅ 修复方案2:package.json 中设置 "type": "module"
另外说一下:这里说的是 Rspack 自己的包变成 ESM,不影响你用 Rspack 构建 CommonJS 产物的能力。构建行为和配置方式跟以前一样。
1.4 产物优化:tree shaking 全面加强
Rspack 2.0 在静态分析能力上做了大幅增强:
1. CommonJS require 解构也能 tree shake 了
js
// ✅ 支持 tree shake:静态解构
const { bar } = require('./foo');
// ❌ 不支持 tree shake:运行时属性访问
const foo = require('./foo');
const bar = foo.bar;
// ❌ 不支持 tree shake:条件导出
module.exports = process.env.NODE_ENV === 'development' ? devApi : prodApi;
这个优化依赖于 exports 对象的静态可分析性 。如果你的 CJS 模块存在运行时条件导出或动态属性赋值(module.exports['prop' + 'Name']),Rspack 会保守起见保留整个模块。建议在这种情况显式声明 sideEffects: false 来辅助判断。
2. 构建器注解 #__NO_SIDE_EFFECTS__
js
/*#__NO_SIDE_EFFECTS__*/
export function join(a, b) {
return `${a}-${b}`;
}
js
import { join } from './utils';
join('btn', 'primary'); // 返回值没被使用 → 整个调用会被移除
这个功能目前还是实验性的,需要通过 experiments.pureFunctions 开启,后续版本会默认开启。
顺便说下它和 /*#__PURE__*/ 的区别------可能很多人更熟悉后者。/*#__PURE__*/ 作用于函数调用 (标记某一次具体调用无副作用),而 #__NO_SIDE_EFFECTS__ 作用于函数声明本身 (标记整个函数无副作用)。后者更强大:即使跨模块引用且未使用返回值,Rspack 也能安全删除整个函数调用。以前要做到这件事得靠 webpack-deep-scope-plugin 这类第三方插件,现在原生支持了。
3. 模块联邦(Module Federation) tree shaking
以前用模块联邦的 shared 声明依赖,运行时会加载完整包。现在可以开启 treeShaking 选项,只打包实际用到的导出:
js
// 方式1:运行时自动推断(推荐,无需手动声明用到的导出)
new rspack.container.ModuleFederationPlugin({
shared: {
'lodash-es': {
singleton: true,
treeShaking: { mode: 'runtime-infer' },
},
},
})
// 方式2:手动指定使用的导出(确定性更高)
new rspack.container.ModuleFederationPlugin({
shared: {
'lodash-es': {
singleton: true,
treeShaking: {
mode: 'manual',
usedExports: ['debounce'], // 只打包 debounce
},
},
},
})
1.5 React Server Components 实验性支持
Rspack 2.0 开始提供 RSC 的底层构建支持:
- 支持
"use client"声明和模块/函数级别的"use server"声明 - 编译期检查违反 RSC 规范的 API 调用
- 服务端和客户端组件的 CSS 收集与注入
- 同时支持服务端和客户端组件的 HMR
如何手动启用 :需要设置 experiments.rsc: true,并配置 resolve.conditionNames 包含 'react-server' 条件导出,确保服务端构建能正确解析 RSC 专用入口。更推荐通过 rsbuild-plugin-rsc 开箱即用,插件会自动处理 client/server 双端构建配置的分裂,避免你手写两套配置。
能力边界:当前仅支持基础的 RSC 构建链路,不支持 Streaming SSR、Server Actions 等进阶特性。仅推荐与 Modern.js、TanStack Start 等上层框架搭配使用,不建议手动从零配置。目前 Modern.js 已基于 Rspack 提供了完整的 RSC 支持,Rspack 也在跟 TanStack 团队合作,后续会支持 TanStack Start。
1.6 其他值得关注的新特性
| 特性 | 说明 |
|---|---|
import.meta 支持 |
保留无法识别的 import.meta 属性,不再替换为 undefined |
import defer 支持 |
stage-3 提案,延后模块求值,TS 5.9 已支持 |
modern-module 库构建 |
生成更适合库发布的 ESM 产物,保留目录结构 |
#/ 子路径别名 |
直接用 package.json 的 imports 字段,不用额外配 alias |
| 简化 target 配置 | 顶层 target 自动继承到 loader 和压缩插件,不用重复声明 |
| 简化 swc-loader 配置 | detectSyntax: 'auto' 自动推断语法,一条规则覆盖所有文件类型 |
| 哈希模块 ID | optimization.moduleIds: 'hashed',更短更稳定的模块 ID |
| 代码分割改进 | 支持 splitChunks.enforceSizeThreshold,强制拆分大 chunk |
2. Why:为什么需要 Rspack 2.0?
2.1 webpack 的痛,Vite 解决不了的部分
前端构建工具的格局在 2026 年变成了"三足鼎立":

Vite 在中小型项目上依然是王者------零配置启动、HMR 极快、插件生态丰富。到 2026 年 Vite 的生产构建底层已切换至 Rolldown(Rust),大型项目的构建性能也有了质变。但 Rspack 在两个场景上依然有不可替代性:一是微前端主应用的子应用加载 (webpack 的 ModuleFederationPlugin 生态深度依赖),二是需要深度定制 webpack compiler hooks 的企业级项目。Vite 的生产构建走 Rollup/Rolldown 路线,跟 webpack 的 loader/plugin 生态天然不兼容,这不是性能问题,是路线问题。
Rspack 的核心差异化就一句话:让 webpack 生态的项目低成本获得 Rust 级别的性能。
这不是一个小市场。全球有海量的 webpack 项目,它们的配置文件、自定义 loader、公司内部的插件------这些东西不是想扔就能扔的。Rspack 对 webpack 常用 API 与主流生态有 95% 左右的兼容度,意味着大多数项目改个包名就能跑起来。
2.2 1.x 阶段的回顾:目标达成
Rspack 1.0 在 2024 年 8 月发布,设定的目标是"在保持 webpack 兼容的前提下实现 10 倍性能提升"。
从 1.0 到 2.0 发布的近两年间,做到了什么?
- 周下载量从 10 万增长到 500 万------50 倍增长
- 陆续引入增量构建、按需编译、持久化缓存、常量折叠(Constant Folding)、桶文件(Barrel 文件,即 index 统一导出文件)优化等特性
- 围绕 Rspack 打造了完整工具链 Rstack(Rsbuild、Rslib、Rstest、Rspress、Rsdoctor、Rslint)
- 社区支持:Angular、Nuxt、Next.js、Storybook、Docusaurus、Modern.js 等框架已提供 Rspack 适配
2.3 为什么要搞 2.0?
Rspack 团队自己说得很直白:
"Rspack 的目标不只是成为一个「更快的 webpack」。在 1.x 阶段,我们有意让 Rspack 的 API 和默认值与 webpack 5 保持一致,这是为了帮助现有项目低成本迁移。但随着 JavaScript 模块规范和生态的发展,一些历史设计已不再适合作为当下的默认选择。"
1.x 是"长得像 webpack"来吸引你迁移,2.0 开始"做自己"。
2.0 的 ESM 化、RSC 支持、产物优化、配置简化------这些都不是 webpack 会做的事情。Rspack 在保持兼容的前提下,开始引入更符合 2026 年 JavaScript 生态的默认行为。
3. 怎么用上 Rspack 2.0?
3.1 新项目直接用Rsbuild
如果你是首次使用 Rspack,推荐直接用 Rsbuild(Rspack 驱动的开箱即用构建工具):
bash
npm create rsbuild@latest
Rsbuild 2.0 已经跟 Rspack 2.0 同步发布,开箱即用,不需要折腾配置。
3.2 从 Rspack 1.x 升级
第一步:升级依赖
json
{
"devDependencies": {
"@rspack/core": "^2.0.0",
"@rspack/cli": "^2.0.0",
"@rspack/dev-server": "^2.0.0",
"@rspack/plugin-react-refresh": "^2.0.0"
}
}
第二步:确认 Node.js 版本
Rspack 2.0 要求 Node.js 20.19+ 或 22.12+,不再支持 Node.js 18。
bash
node -v
# 如果低于 20.19,先升级 Node.js
第三步:处理 Breaking Changes
主要的破坏性变更:
| 变更 | 影响 | 解决方案 |
|---|---|---|
移除 module.unsafeCache |
缓存配置需调整 | 用 cache.type: 'persistent' 替代 |
@rspack/cli 不再默认依赖 @rspack/dev-server |
rspack serve 命令需要手动安装 dev-server |
npm add @rspack/dev-server -D |
resolve.exportsPresence 默认值从 warn 改为 error |
导出不存在时直接报错 | ⚠️ 最容易导致 CI 构建失败的破坏性变更!许多第三方库的 exports 字段书写不规范会被误杀。升级后如果构建失败,可在 resolve.exportsPresence 设为 'warn' 降级为警告(不中断构建) |
builtin:swc-loader 不再读 .swcrc |
SWC 配置需迁移到 loader options | 把配置移到 rspack.config.mjs |
output.chunkLoadingGlobal 默认值变更 |
chunk 全局变量名从 webpackChunk 变为 rspackChunk |
如有依赖可显式配置 |
webpack-bundler-analyzer 被移除 |
--analyze 参数失效 |
改用 Rsdoctor |
output.libraryTarget 等配置迁移 |
库构建配置语法变更 | 迁移到 output.library.type |
devServer.hot 默认值变更 |
热更新默认不再自动开启 | 需手动配置 devServer.hot: true,否则升级后 HMR 失效 |
| 统计输出(stats)配置重构 | 部分 webpack 兼容的 stats 字段被移除 | 自定义日志输出需适配新格式 |
resolve.exportsPresence 降级示例:
js
export default defineConfig({
resolve: { exportsPresence: 'warn' },
});
第四步(可选):用 Agent 辅助迁移
如果你在用 Coding Agent(比如 Cursor、Claude Code 等),可以安装 Rspack 官方的迁移 Skill:
bash
npx skills add rstackjs/agent-skills --skill rspack-v2-upgrade
装好后让 Agent 帮你完成升级,通常比手动改更高效。
3.3 从 webpack 迁移
如果你还在用 webpack,Rspack 的迁移路径已经非常成熟了。核心步骤:
bash
# 1. 安装 Rsbuild(最简路径)
npm create rsbuild@latest
# 2. 选择 "Convert from webpack" 模式
# Rsbuild 会自动尝试转换你的 webpack.config.js
或者手动迁移:
js
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { defineConfig } from '@rspack/core';
// 2.0 推荐 ESM 配置文件,不再默认有 __dirname,需手动声明
const __dirname = path.dirname(fileURLToPath(import.meta.url));
export default defineConfig({
entry: './src/index.js',
output: {
path: path.resolve(__dirname, './dist'), // 必须使用绝对路径
},
module: {
rules: [
{
test: /\.(?:js|mjs|jsx|ts|tsx)$/,
use: {
loader: 'builtin:swc-loader',
options: {
// 2.0 新特性:自动推断语法,替代手写 syntax + jsx/tsx 布尔值
detectSyntax: 'auto',
jsc: {
transform: {
react: {
runtime: 'automatic',
},
},
},
},
},
},
],
},
});
2.0 新增的 detectSyntax: 'auto' 大幅简化了多文件类型的 loader 配置
以前要写多条 rules 分别处理 .js、.jsx、.ts、.tsx,还要手动指定 jsc.parser.syntax、jsx、tsx 等选项,现在一条规则全搞定,根据文件扩展名自动推断该用哪种语法解析。
注意:
output.path必须传绝对路径 ,直接写相对路径在 ESM 配置文件下会报错。因为 2.0 推荐用 ESM 配置文件,不再默认有__dirname,需要通过fileURLToPath手动声明------这是很多用户升级会踩的坑。
3.4 从 webpack 迁移要注意什么
需要注意的是,95% 兼容主要覆盖常用 API 与主流生态,深度定制的项目迁移仍可能遇到兼容性问题。几个常见问题:
1. 自定义 webpack 插件
如果你的项目有自己写的 webpack 插件,需要检查是否用到了 Rspack 未实现的 API。大部分插件的 tapable hooks 都是兼容的,但一些边缘 API 可能没覆盖。
2. 特定 loader 兼容性
大部分常用 loader(babel-loader、css-loader、style-loader、postcss-loader)都是兼容的。但一些小众 loader 可能有问题,需要在 Plugin 兼容列表 里查一下。
3. 模块联邦
Rspack 支持模块联邦,但 @module-federation/runtime-tools 在 2.0 中变成了可选依赖。如果你用了模块联邦,需要手动安装:
bash
npm add @module-federation/runtime-tools
4. 产物验证与灰度方案
大型项目迁移最关心风险控制,建议分阶段推进:
- 开发环境先切------先在开发环境切换到 Rspack,验证 HMR、代理、静态资源等基础功能
- 生产环境双构建对比------同时跑 webpack 和 Rspack 生产构建,对比产物体积、sourcemap、核心功能回归
- 逐步全量------确认无差异后,逐步将 CI 流水线切换到 Rspack
4. 该选谁?
| 维度 | Rspack 2.0 | Vite | Turbopack |
|---|---|---|---|
| 底层语言 | Rust | Rust (Rolldown 生产构建) | Rust |
| webpack 兼容 | ⭐⭐⭐⭐⭐ (常用 API ~95%) | ❌ | ❌ |
| 开发体验 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ (仅 Next.js) |
| 大型项目构建 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 产物质量 / Tree Shaking | ⭐⭐⭐⭐⭐ (CJS + ESM 均强) | ⭐⭐⭐⭐⭐ (纯 ESM 项目上限更高,CJS 兼容项目弱于 Rspack) | ⭐⭐⭐⭐ |
| 生态成熟度 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| RSC 支持 | ✅ (实验性,基础链路) | ✅ (通过框架) | ✅ (Next.js) |
| 适用场景 | webpack 迁移 / 大型项目 | 中小型 SPA | Next.js 项目 |
| 维护方 | 字节跳动 | VoidZero (尤雨溪) | Vercel |
并不是说 Rolldown 跑不动大项目,它在底层性能上已经足够优秀。差异在于生态兼容性:Vite 的产物构建走 Rollup/Rolldown 链路,无法直接复用 webpack 的 loader 和插件。如果你的大型项目重度依赖 webpack 生态(比如自定义 compiler hooks、特定的 webpack loader),Rspack 是更平滑的选择。
一个比较务实的选型原则:
- 新项目,中小型 SPA → Vite,开发体验最好,Rolldown 核心已经成熟
- webpack 存量项目 → Rspack,迁移成本最低,常用 API 95% 兼容
- Next.js 项目 → Turbopack,原生集成,Next.js 专属第一公民
- 微前端 / 深度定制 webpack hooks → Rspack,ModuleFederation 和 compiler hooks 生态不可替代
- 不确定 / 想留后路 → Rspack,因为它的 webpack 兼容性给你最大的退路
5. Q&A
Q1: Rspack 和 webpack 的核心区别是什么?
核心区别是底层实现语言。webpack 用 JavaScript 编写,受限于 Node.js 单线程模型和 V8 引擎的 GC 压力;Rspack 用 Rust 编写核心,利用 Rust 的内存安全、零成本抽象和多线程能力。性能方面,无缓存首次构建约为 webpack 的 5-10 倍,持久化缓存命中场景可达 20 倍以上。同时 Rspack 对 webpack 常用 API 与主流生态有约 95% 的兼容度,大幅降低迁移成本。
Q2: Rspack 2.0 转为纯 ESM 包,对使用者有什么影响?
对大多数项目没有影响。Node.js 22.12+ 已稳定支持 CommonJS 中通过
require()加载 ESM 模块,20.19+ 为实验性支持。所以即使你的项目是 CommonJS 的,在符合 Node 版本要求的前提下也能正常使用 Rspack 2.0。⚠️ 但有一个边界情况:如果 ESM 模块内部使用了顶层 await(Top-level await) ,
require()会直接抛出ERR_REQUIRE_ASYNC_MODULE错误,无法绕过。目前 Rspack 2.0 核心包自身没有使用顶层 await,但如果你在配置文件中引入的第三方 ESM 依赖含有顶层 await,CJS 项目就会挂掉。解决方案:把rspack.config.js改名为rspack.config.mjs,或在package.json中设置"type": "module",将项目切换为 ESM 模式。另外,Rspack 2.0 不再支持 Node.js 18,最低要求 20.19+ 或 22.12+。
Q3: 什么是 #__NO_SIDE_EFFECTS__ 注解?它解决了什么问题?
这是构建器注解(Bundler Annotations)规范中定义的注解,用于将函数标记为无副作用。当被标记函数的调用返回值未被使用时,tree shaking 可以安全移除该调用。这解决了一个长期问题:跨模块的函数调用,即使返回值没被使用,因为函数体可能有副作用(比如修改全局变量、发请求),打包工具不敢删。有了这个注解,打包工具就知道可以安全删除。
Q4: Rspack 2.0 的依赖瘦身为什么重要?
两个原因。第一,依赖越少,安装越快,磁盘占用越小------
@rspack/dev-server从 15MB 降到 1.4MB 是实打实的体感提升。第二,依赖越少,供应链风险越低。npm 生态中一个传递依赖被投毒或意外破坏的事件并不罕见。Rspack 通过把依赖打包进发布产物(vendor 化)、用 Node.js 原生 API 替代第三方包等方式,大幅降低了这种风险。但要注意,vendor 化意味着你无法通过npm overrides直接升级传递依赖版本来修复 CVE 漏洞,需依赖官方发版;patch-package虽可对打包后的产物生效,但维护成本极高,不推荐企业级项目使用。
Q5: 在什么场景下应该选择 Rspack 而不是 Vite?
两个典型场景:1)有大量 webpack 存量代码 ------包括自定义 loader、插件、配置文件,或重度依赖 webpack 特有的能力(如模块联邦、特定的 compiler hooks),迁移到 Vite 意味着重写整个构建链路,成本远高于切换到 Rspack;2)微前端主应用------需要与多个基于 webpack 构建的子应用协同,Rspack 的模块联邦生态兼容性是刚需。
反之,如果是从零开始的中小型 SPA,不涉及 webpack 历史包袱,Vite 的零配置开发体验依然是首选。
参考资料:
- Rspack 2.0 发布公告 - 官方博客
- Rspack 2.0 升级指南
- InfoQ: RSPack 2.0 性能提升、更精简的依赖项和 ESM 核心
- rspack-react-10k-benchmark
以上就是本节的全部内容,如果你觉得有收获,欢迎关注,持续分享好文,下期见~