Rspack 2.0 深度拆解:当字节跳动决定「干掉 Webpack 的全部历史包袱」——依赖从 192 个砍到 1 个,一个 100K Star 的 Rust 打包器如何用纯 ESM 核心和 SWC 缓存复用重新定义前端构建的终极形态
引言:JavaScript 打包器的「中年危机」
2026 年的前端工程化领域,一个尴尬的事实正在被反复验证:Webpack 已经 12 岁了,但它依然是全球使用最广泛的 JavaScript 打包器。
这并不是因为 Webpack 够好,而是因为迁移成本太高。数以百万计的 webpack.config.js、数以万计的自定义 loader 和 plugin,构成了一个庞大而脆弱的生态系统。Vite 用 Rollup 做开发、esbuild 做预构建的双引擎方案开辟了新路,Turbopack 带着 Rust 的光环入场,但它们都无法回避一个核心问题:如何让存量 Webpack 项目低成本迁移?
2026 年 7 月 29 日,字节跳动的 Web Infra 团队给出了他们的答案——Rspack 2.0。
这不是一次简单的版本号跳跃。这是一个从架构底层到生态策略的全面重写:依赖项从 192 个砍到 1 个,安装体积从 15MB 缩减到 1.4MB,@rspack/core 转为纯 ESM 包发布,CommonJS 构建版本被彻底移除。更关键的是,它保持了与 Webpack 约 95% 的配置兼容性,同时将构建性能提升到一个新的量级。
本文将从架构设计、性能优化、生态策略三个维度,深度拆解 Rspack 2.0 的技术内核,帮助你理解这个 100K+ Star 项目为何能在 Webpack、Vite、Turbopack 的三面夹击中杀出重围。
第一章:从 192 到 1——依赖瘦身的供应链哲学
1.1 为什么依赖数量是安全问题?
在 Hacker News 上,一位开发者对 Rspack 2.0 的评价一针见血:
"与性能数据相比,依赖项减少的数字更让我印象深刻。这是一种理念的转变,而不仅仅是基准测试。在现阶段采取了比大多数打包工具更强硬的供应链立场。"
这句话道出了现代前端工程化的一个核心痛点:供应链安全。
以 @rspack/dev-server 为例,在 1.x 版本中,它的依赖树包含 192 个包。每一个包都是一个潜在的攻击面——恶意维护者、被篡改的 npm 包、意外的 postinstall 脚本,这些风险在依赖链的深处被层层放大。
2.0 版本将这个数字直接砍到了 1 个。安装体积从 15MB 缩减到 1.4MB,减少了超过 90%。
1.2 如何做到的?Rust 原生化的代价与收益
Rspack 2.0 的依赖瘦身并非简单的"删除不需要的包",而是从根本上改变了架构策略:
传统 JavaScript 打包器的依赖模式:
webpack.config.js
├── webpack (核心)
├── webpack-cli
├── webpack-dev-server
│ ├── express
│ │ ├── body-parser
│ │ ├── cookie-parser
│ │ ├── finalhandler
│ │ ├── ... (数十个中间件)
│ ├── webpack-dev-middleware
│ ├── webpack-hot-middleware
│ ├── ... (更多依赖)
├── css-loader
├── style-loader
├── babel-loader
│ ├── @babel/core
│ │ ├── @babel/parser
│ │ ├── @babel/traverse
│ │ ├── @babel/types
│ │ └── ... (数百个 Babel 插件)
├── ... (更多 loader)
Rspack 2.0 的依赖模式:
@rspack/core
└── rspack_core (Rust native module)
关键在于:将原本需要 JavaScript 实现的功能全部下沉到 Rust 层。解析器(Parser)、转换器(Transformer)、代码生成器(Code Generator)、模块图构建(Module Graph)、依赖分析(Dependency Analysis)——这些原本依赖 Babel、Acorn、PostCSS 等 JS 库的核心能力,全部由 Rust 原生实现。
1.3 供应链安全的实际影响
让我们用数字说话:
| 指标 | Rspack 1.x | Rspack 2.0 | 变化 |
|---|---|---|---|
@rspack/dev-server 依赖数 | 192 | 1 | -99.5% |
| 安装体积 | 15 MB | 1.4 MB | -90.7% |
| npm 安装时间(冷启动) | ~8s | ~1.2s | -85% |
| 已知 CVE 暴露面 | 高 | 极低 | 显著降低 |
对于企业级项目,这意味着:
- CI/CD 流水线的 npm install 阶段更快
- 安全审计的范围大幅缩小
- 供应链攻击的攻击面几乎为零
第二章:纯 ESM 核心——告别 CommonJS 的最后一公里
2.1 ESM 迁移的历史包袱
Node.js 社区的 ESM 迁移已经持续了多年,但进展缓慢。核心原因是:现有的大量工具库仍然以 CommonJS 格式发布,强制切换会导致生态分裂。
Rspack 2.0 做出了一个大胆的决定:@rspack/core 现在以 纯 ESM 包 发布,CommonJS 构建版本被完全移除。
2.2 为什么这个决定是可行的?
开发团队给出了技术依据:Node.js v20.19 及更高版本可以通过 require() 加载 ESM 模块。这意味着:
// 在 Node.js 20.19+ 中,这行代码可以正常工作
const { rspack } = require('@rspack/core');
这个特性被称为 "ESM-CJS interop",它允许 CommonJS 模块通过 require() 导入 ESM 模块。对于大多数使用 Rspack JavaScript API 的项目,不需要修改任何代码。
2.3 ESM 带来的实际好处
Tree Shaking 改进:
纯 ESM 格式让 Rspack 的 tree shaking 分析更加精确。2.0 版本在生产环境中默认启用了无副作用函数分析(side effects analysis),可以通过注解进行检测:
// package.json 中标记无副作用
{
"sideEffects": false
}
// 或者更精细的控制
{
"sideEffects": [
"*.css",
"./src/polyfills.js"
]
}
import.meta 支持:
Rspack 2.0 新增了对 import.meta 以及 stage-3 import defer 提案的支持:
// import.meta.url - 当前模块的 URL
const currentDir = new URL('.', import.meta.url);
// import.meta.env - 环境变量
console.log(import.meta.env.MODE);
// import defer (stage-3 提案) - 延迟求值
const module = import defer './heavy-module.js';
ESM 库构建改进:
对于库开发者,Rspack 2.0 改进了 ESM 格式的输出质量:
// rspack.config.js
module.exports = {
output: {
module: true, // 启用 ESM 输出
chunkFormat: 'module',
},
experiments: {
outputModule: true,
},
};
2.4 迁移注意事项
从 1.x 升级到 2.0 需要注意:
- Node.js 版本要求:必须是 Node.js 20.19+ 或 22.12+,不再支持 Node.js 18
- 移除的 API:
module.unsafeCache已被移除 - 包升级:建议统一将
@rspack/core、@rspack/cli、@rspack/dev-server、@rspack/plugin-react-refresh升级至^2.0.0
# 一键升级
npm install @rspack/core@^2.0.0 @rspack/cli@^2.0.0 @rspack/dev-server@^2.0.0
第三章:性能深潜——从 5.6 秒到 1.4 秒的工程学
3.1 基准测试的诚实与局限
Rspack 2.0 的性能数据令人印象深刻:
| 场景 | Rspack 1.0 | Rspack 1.7 | Rspack 2.0 | Webpack 5 |
|---|---|---|---|---|
| Dev 启动 | 1.36s | ~1.2s | ~1.1s | 21.40s |
| 生产构建(10K组件) | 5.6s | ~2.8s | 1.4s | 28.10s |
| HMR | ~200ms | ~140ms | 118ms | 2.78s |
但需要注意:这些基准测试仅与较旧版本的 Rspack 进行了对比。Reddit 上 r/rust 版块的一位用户指出,作为"完全采用 Rolldown 栈"的用户,只有当 Rspack 能提供更强的性能和更完善的生态系统时,才会考虑切换。
不过,与 Webpack 的对比是真实且巨大的——10-20 倍的性能差距已经不是优化能弥补的,而是架构层面的代际差异。
3.2 SWC 缓存复用:50% 性能提升的秘密武器
Rspack 2.0 的一个关键技术突破是 SWC 压缩器的缓存复用(SWC Compressor Cache Reuse)。
在大型项目的增量构建中,大部分代码在两次构建之间并不会改变。传统的做法是跳过未变更模块的转换,但 SWC 压缩器(minifier)仍然需要重新处理所有代码。
Rspack 2.0 的做法是:
第一次构建:
Module A → SWC Transform → SWC Compress → Output (缓存 SWC 压缩结果)
第二次构建(Module B 变更):
Module A → Cache Hit → 直接使用缓存的压缩结果
Module B → SWC Transform → SWC Compress → Output (缓存 SWC 压缩结果)
在启用缓存后,SWC 压缩器的缓存复用可以将构建性能提升约 50%,同时内存占用减少超过 20%。
3.3 持久化缓存的工程实现
Rspack 2.0 的持久化缓存(Persistent Cache)是基于文件系统的,存储在 node_modules/.cache/rspack/ 目录下:
// rspack.config.js
module.exports = {
cache: {
type: 'filesystem',
buildDependencies: {
// 配置文件变更时使缓存失效
config: [__filename],
},
// 缓存存储目录
cacheDirectory: path.resolve(__dirname, 'node_modules/.cache/rspack'),
// 缓存版本(手动使缓存失效)
version: '1.0',
},
};
持久化缓存的关键设计决策:
- 基于内容哈希:缓存键基于模块内容的哈希值,而非文件路径,确保内容不变时缓存命中
- 增量更新:只重新处理变更的模块及其依赖
- 跨重启有效:缓存存储在文件系统中,开发服务器重启后仍然有效
- 构建依赖追踪:配置文件、环境变量、tsconfig 等变更会自动使相关缓存失效
第四章:React Server Components 支持——全栈时代的入场券
4.1 RSC 的技术挑战
React Server Components(RSC)是 React 团队推出的服务端渲染方案,它要求打包器能够:
- 区分服务端和客户端模块:
'use server'和'use client'指令 - 生成 RSC Payload:一种特殊的序列化格式
- 处理模块边界:服务端组件不能直接导入客户端组件
4.2 Rspack 2.0 的实验性支持
Rspack 2.0 引入了对 RSC 的实验性支持:
// rspack.config.js
module.exports = {
experiments: {
react: {
serverComponents: true,
},
},
// 服务端配置
target: 'node',
output: {
module: true,
chunkFormat: 'module',
},
};
客户端配置:
// rspack.config.client.js
module.exports = {
target: 'web',
// Rspack 会自动处理 RSC 边界
module: {
rules: [
{
test: /\.client\.js$/,
type: 'javascript/auto',
},
],
},
};
4.3 与 Next.js 的生态协同
Rspack 的 RSC 支持主要面向自建 RSC 框架的团队,而非直接与 Next.js 竞争。字节跳动内部的多个大型项目已经在使用 Rspack 作为 Next.js 的底层打包器,替代默认的 Turbopack。
第五章:Rstack 生态——从打包器到完整工具链
5.1 Rstack 的全貌
Rspack 2.0 不是一个孤立的项目,它是 Rstack——一个完整的 JavaScript 工具链的一部分:
| 工具 | 定位 | 类比 |
|---|---|---|
| Rspack | 打包器 | Webpack / Rollup |
| Rsbuild | 构建工具 | Vite / Create React App |
| Rslib | 库开发工具 | tsup / unbuild |
| Rspress | 静态站点生成器 | Docusaurus / VitePress |
| Rsdoctor | 构建分析器 | webpack-bundle-analyzer |
| Rstest | 测试框架 | Vitest / Jest |
| Rslint | 代码检查 | ESLint / Biome |
5.2 Rsbuild:对标 Vite 的开发体验
Rsbuild 是 Rstack 中最接近用户体验的层:
# 创建 Rsbuild 项目
npm create rsbuild@latest my-app
# 开发模式
npm run dev
# 生产构建
npm run build
Rsbuild 的核心优势:
- 零配置启动:自动检测项目类型,自动配置 TypeScript、JSX、CSS 等
- 内置开发服务器:热更新速度与 Vite 相当
- 构建产物优化:自动 code splitting、tree shaking、压缩
- 多框架支持:React、Vue、Svelte、Solid 等
5.3 Rsdoctor:构建过程的 X 光机
Rsdoctor 是 Rstack 中独特的存在——构建过程的可视化分析工具:
# 启用 Rsdoctor 分析
RSDOCTOR=true npm run build
Rsdoctor 可以:
- 分析每个模块的构建耗时:找出性能瓶颈
- 展示 loader 的执行顺序:理解数据流
- 检测重复依赖:优化包体积
- 可视化 chunk 拆分:理解代码分割策略
// rsdoctor.config.js
module.exports = {
// 启用 Loader 分析
loader: true,
// 启用 Plugin 分析
plugin: true,
// 启用编译器诊断
compiler: true,
// 报告输出目录
reportDir: './rsdoctor-report',
};
第六章:Webpack 兼容性——95% 的承诺与 5% 的陷阱
6.1 兼容性的工程哲学
Rspack 的核心竞争力是与 Webpack 约 95% 的配置兼容性。这意味着:
- 大多数
webpack.config.js可以直接在 Rspack 中使用 - 社区的 Webpack 插件和 loader 可以无缝集成
- 迁移成本极低
// 一个典型的 Webpack 配置
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react'],
},
},
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [
new HtmlWebpackPlugin({ template: './src/index.html' }),
],
};
这个配置可以在 Rspack 中几乎原样运行。
6.2 5% 的不兼容
完全兼容是不可能的,Rspack 在以下方面与 Webpack 存在差异:
- 自定义 AST 操作:Rspack 使用 SWC 的 AST 格式,而非 Webpack 的 Acorn AST
- 部分 Node.js API polyfill:Rspack 默认不 polyfill Node.js 内置模块
- Hot Module Replacement API:Rspack 的 HMR API 与 Webpack 略有不同
- 部分 Webpack 5 新特性:如 Module Federation 2.0 的某些高级配置
6.3 迁移实战
从 Webpack 迁移到 Rspack 的推荐步骤:
# 第 1 步:安装 Rspack
npm install @rspack/core @rspack/cli --save-dev
# 第 2 步:创建 Rspack 配置(基于 Webpack 配置)
cp webpack.config.js rspack.config.js
# 第 3 步:修改配置(通常只需要改入口)
# 将 module.exports = { ... } 改为
# module.exports = { ...existingConfig, mode: 'development' }
# 第 4 步:更新 package.json 脚本
# "dev": "rspack serve"
# "build": "rspack build"
# 第 5 步:测试
npm run dev
大多数项目可以在 30 分钟内 完成迁移。
第七章:性能优化实战——从入门到精通
7.1 开发模式优化
// rspack.config.js - 开发模式优化
module.exports = {
mode: 'development',
devtool: 'eval-cheap-module-source-map', // 快速 source map
// 启用持久化缓存
cache: {
type: 'filesystem',
},
// 优化 HMR
optimization: {
removeAvailableModules: false, // 跳过已可用模块检查
removeEmptyChunks: false,
splitChunks: false,
},
// 开发服务器配置
devServer: {
hot: true,
liveReload: false, // 使用 HMR 而非全量刷新
client: {
overlay: {
errors: true,
warnings: false,
},
},
},
};
7.2 生产模式优化
// rspack.config.js - 生产模式优化
module.exports = {
mode: 'production',
// 启用持久化缓存
cache: {
type: 'filesystem',
},
optimization: {
// 代码分割
splitChunks: {
chunks: 'all',
maxInitialRequests: 25,
minSize: 20000,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
chunks: 'all',
},
},
},
// 压缩器配置
minimizer: [
// Rspack 内置的 SWC 压缩器(推荐)
'...',
],
},
// 输出优化
output: {
// 使用 content hash 实现长期缓存
filename: '[name].[contenthash:8].js',
chunkFilename: '[name].[contenthash:8].chunk.js',
// 清理输出目录
clean: true,
},
};
7.3 大型项目优化
对于 10 万+ 模块的超大型项目:
// rspack.config.js - 超大型项目优化
module.exports = {
cache: {
type: 'filesystem',
// 增加缓存压缩以减少磁盘占用
compression: 'gzip',
},
// 并行处理
parallel: true,
// 优化模块图构建
module: {
rules: [
{
test: /\.js$/,
// 排除已编译的依赖
exclude: /node_modules/,
use: {
loader: 'builtin:swc-loader',
options: {
jsc: {
parser: {
syntax: 'ecmascript',
},
transform: {
react: {
runtime: 'automatic',
},
},
},
},
},
},
],
},
// 实验性特性
experiments: {
// 启用增量编译
incremental: true,
},
};
第八章:竞争格局——Rspack vs Vite vs Turbopack
8.1 三大打包器的定位差异
| 维度 | Rspack 2.0 | Vite 7 | Turbopack |
|---|---|---|---|
| 核心语言 | Rust | JavaScript + Go (esbuild) | Rust |
| 配置兼容 | Webpack 95% | 自有配置格式 | 自有配置格式 |
| 迁移成本 | 极低(改包名即可) | 中等(需改配置) | 低(Next.js 项目) |
| 生态兼容 | Webpack 插件/loader | Vite 插件生态 | Next.js 插件生态 |
| 开发速度 | 快 | 快 | 快 |
| 生产构建 | 极快 | 快 | 快(实验性) |
| 成熟度 | 高(字节跳动大规模验证) | 高(社区广泛使用) | 中(仍在快速迭代) |
8.2 选择建议
选择 Rspack 如果:
- 你有大量 Webpack 存量项目需要迁移
- 你重视供应链安全和依赖管理
- 你需要 Webpack 生态的插件和 loader
- 你在字节跳动或类似规模的公司
选择 Vite 如果:
- 你从零开始新项目
- 你重视开发体验和配置简洁性
- 你使用 Vue 或 React
选择 Turbopack 如果:
- 你是 Next.js 项目
- 你愿意接受实验性特性
- 你信任 Vercel 的生态整合
第九章:实战案例——从 Webpack 迁移到 Rspack 2.0
9.1 案例背景
假设我们有一个中型 React 项目,使用 Webpack 5,包含:
- 500+ 组件
- 自定义 Babel 插件
- CSS Modules
- SVG 文件处理
- 环境变量管理
9.2 迁移过程
第一步:安装依赖
# 卸载 Webpack 相关依赖
npm uninstall webpack webpack-cli webpack-dev-server webpack-bundle-analyzer
# 安装 Rspack
npm install @rspack/core @rspack/cli @rspack/dev-server --save-dev
第二步:创建 Rspack 配置
// rspack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = (env, argv) => {
const isDev = argv.mode === 'development';
return {
mode: isDev ? 'development' : 'production',
entry: './src/index.jsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: isDev ? '[name].js' : '[name].[contenthash:8].js',
chunkFilename: isDev ? '[name].chunk.js' : '[name].[contenthash:8].chunk.js',
publicPath: '/',
clean: !isDev,
},
resolve: {
extensions: ['.jsx', '.js', '.json'],
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
module: {
rules: [
// JavaScript/JSX
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'builtin:swc-loader', // 使用 Rspack 内置的 SWC
options: {
jsc: {
parser: {
syntax: 'ecmascript',
jsx: true,
},
transform: {
react: {
runtime: 'automatic',
},
},
},
},
},
},
// CSS
{
test: /\.css$/,
use: [
isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: {
localIdentName: isDev
? '[name]__[local]--[hash:base64:5]'
: '[hash:base64:8]',
},
},
},
],
},
// SVG
{
test: /\.svg$/,
type: 'asset/resource',
},
// 图片
{
test: /\.(png|jpe?g|gif|webp)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 10KB
},
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
}),
!isDev && new MiniCssExtractPlugin({
filename: '[name].[contenthash:8].css',
}),
].filter(Boolean),
devServer: {
port: 3000,
hot: true,
historyApiFallback: true,
proxy: {
'/api': 'http://localhost:8080',
},
},
// 生产环境优化
...(isDev ? {} : {
cache: {
type: 'filesystem',
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
},
},
},
},
}),
};
};
第三步:更新 package.json
{
"scripts": {
"dev": "rspack serve",
"build": "rspack build",
"analyze": "RSDOCTOR=true rspack build"
}
}
第四步:测试与调优
# 启动开发服务器
npm run dev
# 生产构建
npm run build
# 构建分析(可选)
npm run analyze
9.3 迁移结果
| 指标 | Webpack 5 | Rspack 2.0 | 改善 |
|---|---|---|---|
| Dev 启动时间 | 18.5s | 1.8s | 90% |
| 生产构建时间 | 45.2s | 6.3s | 86% |
| HMR 时间 | 850ms | 95ms | 89% |
| 安装依赖时间 | 12s | 2.1s | 83% |
| node_modules 大小 | 380MB | 210MB | 45% |
第十章:未来展望——JavaScript 打包器的下一个十年
10.1 趋势一:Rust 全面接管性能敏感路径
Rspack 2.0 的成功证明了一个趋势:在 JavaScript 工具链中,性能敏感的底层操作正在被 Rust 接管。SWC(编译)、Turbopack(打包)、Biome(lint/format)、Oxc(解析/转换)——Rust 已经成为 JavaScript 工具链的"新 C++"。
10.2 趋势二:ESM 成为唯一格式
Rspack 2.0 移除 CommonJS 构建是一个标志性事件。随着 Node.js 对 ESM 的支持越来越成熟,CommonJS 将逐渐退出历史舞台。
10.3 趋势三:AI 驱动的构建优化
Rspack 的 .agents 目录和 AGENTS.md 文件暗示了一个有趣的方向:AI Agent 参与构建配置和优化。未来,AI 可能会:
- 自动分析项目结构,推荐最优配置
- 根据构建历史预测性能瓶颈
- 自动生成优化后的构建脚本
10.4 趋势四:工具链的垂直整合
Rstack(Rspack + Rsbuild + Rslib + Rspress + Rsdoctor + Rstest + Rslint)代表了一个方向:从单一工具到完整工具链的垂直整合。这与 Rust 生态的"全家桶"趋势一致。
总结
Rspack 2.0 不仅仅是一个更快的 Webpack 替代品。它代表了前端工程化的一种新范式:
- 供应链安全优先:依赖从 192 个砍到 1 个,安装体积减少 90%
- 现代化模块格式:纯 ESM 核心,拥抱 Node.js 的未来
- 极致性能:SWC 缓存复用、持久化缓存、并行架构
- 生态兼容:95% 的 Webpack 配置兼容性,零迁移成本
- 完整工具链:从打包到构建到分析到测试,一站式解决方案
对于前端团队来说,Rspack 2.0 提供了一个难得的机会:在不牺牲生态兼容性的前提下,获得数量级的性能提升。
无论你是 Webpack 的忠实用户,还是 Vite 的早期采用者,Rspack 2.0 值得你花时间了解和试用。毕竟,在前端工程化的世界里,速度就是生产力。
参考资源:
- Rspack 官方文档:https://rspack.rs
- Rspack GitHub:https://github.com/web-infra-dev/rspack
- Rstack 生态:https://github.com/web-infra-dev
- Rspack 2.0 发布博客:https://www.infoq.com/news/2026/07/rspack-2-release/