Rspack 与 Farm:Rust 构建工具
问题
Rspack 和 Farm 分别是什么?为什么前端社区在向 Rust 构建工具迁移?它们与 Webpack、Vite 有什么关系?当前 Rust 构建工具生态是怎样的?
答案
Rspack 和 Farm 是新一代基于 Rust 的前端构建工具。Rspack 由字节跳动开源,定位为 Webpack 的高性能替代品;Farm 则定位为极速全栈构建工具,提出了独创的 Partial Bundling 策略。它们代表着前端构建工具从"JavaScript/Go 加速单环节"到"Rust 重写整个构建流程"的重大转变。
Rspack = Rust 实现的 Webpack 兼容替代品,Farm = Rust 实现的极速构建工具(Partial Bundling)。两者都旨在用 Rust 的性能优势彻底解决大型项目的构建瓶颈。
为什么需要 Rust 构建工具
JS 工具链的性能瓶颈
尽管 esbuild(Go)和 SWC(Rust)已经大幅提升了编译和转译环节的速度,但整体构建流程仍然存在瓶颈:
| 瓶颈 | 说明 |
|---|---|
| JS 编排层 | Webpack/Vite 的核心调度逻辑仍然是 JavaScript,成为新的瓶颈 |
| 跨语言通信开销 | JS 调用 esbuild/SWC 需要跨进程通信(IPC),数据序列化/反序列化消耗大 |
| 单线程调度 | 即使底层用了 Go/Rust,上层 JS 调度仍受单线程限制 |
| 插件执行 | 大量 Webpack/Vite 插件用 JS 编写,无法被系统语言加速 |
| 内存开销 | 大型项目 Node.js 进程动辄占用数 GB 内存 |
Rust 的核心优势
Rust 语言本身的特性使其非常适合构建工具场景:
| 特性 | 说明 | 对构建工具的意义 |
|---|---|---|
| 零成本抽象 | 高级抽象不引入运行时开销 | 可以写出优雅且高效的代码 |
| 无 GC | 所有权系统管理内存,无垃圾回收暂停 | 构建过程无不可预测的停顿 |
| 内存安全 | 编译期保证无数据竞争、无悬垂指针 | 并行构建不会出现难以调试的内存问题 |
| 真正的并行 | 无 GIL,线程间可安全共享数据 | 解析、转换、代码生成全阶段并行化 |
| 编译为机器码 | AOT 编译,无需 JIT 预热 | 冷启动即达峰值性能 |
Go 也是编译型语言(esbuild 就是用 Go 写的),但 Go 有 GC、不支持零成本抽象,且并发模型(goroutine)在 CPU 密集型任务上不如 Rust 的线程模型。Rust 的所有权系统可以实现零拷贝数据共享,这在处理大量 AST 节点时优势显著。
Rspack 深入解析
什么是 Rspack
Rspack 是由字节跳动 Web Infra 团队开源的高性能 JavaScript 打包工具,使用 Rust 编写,核心定位是 Webpack 的高性能替代品。它实现了大部分 Webpack API,使得现有 Webpack 项目可以低成本迁移,同时获得数十倍的性能提升。
核心特性
关键特性一览:
- Rust 全链路:解析、转换、打包、代码生成全部用 Rust 实现,无跨语言通信开销
- Webpack API 兼容:支持
loader、plugin、module、resolve、optimization等核心配置 - 内置 SWC:无需额外配置
babel-loader,开箱即用支持 TypeScript、JSX、装饰器 - 增量编译:HMR 热更新速度极快,大型项目也能保持毫秒级响应
- Tree Shaking:支持 ESM Tree Shaking,与 Webpack 5 行为一致
- 代码分割:支持动态
import()和splitChunks配置
与 Webpack 的兼容性
Rspack 的最大优势在于对 Webpack 生态的兼容:
| 能力 | 兼容性 |
|---|---|
| webpack.config.js 配置格式 | 高度兼容 |
| Loader(babel-loader、css-loader 等) | 大部分兼容 |
| Plugin(HtmlWebpackPlugin 等) | 部分兼容,提供内置替代 |
| resolve(alias、extensions) | 完全兼容 |
| optimization(splitChunks) | 高度兼容 |
| devServer | 兼容(基于 @rspack/dev-server) |
| Module Federation | 支持(内置) |
以下 Webpack 特性在 Rspack 中尚不完全支持或行为有差异:
- 部分 Plugin API:一些底层 Compiler/Compilation hooks 尚未实现
- Webpack 特有 Loader:依赖 Webpack 内部 API 的 Loader 可能不兼容
compiler.hooks的完整覆盖:部分冷门 hooks 未实现- 某些
resolve高级选项:如resolve.plugins支持有限
迁移前建议查阅 Rspack 兼容性文档 确认项目依赖的特性是否已支持。
配置对比:Rspack vs Webpack
Rspack 的配置与 Webpack 高度相似,迁移成本极低:
import path from 'path';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import type { Configuration } from 'webpack';
const config: Configuration = {
entry: './src/index.tsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'babel-loader', // 需要 Babel 配置
exclude: /node_modules/,
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [
new HtmlWebpackPlugin({ template: './index.html' }),
],
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
};
export default config;
import path from 'path';
import type { Configuration } from '@rspack/cli';
const config: Configuration = {
entry: './src/index.tsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'builtin:swc-loader', // 内置 SWC,无需 Babel
options: {
jsc: {
parser: { syntax: 'typescript', tsx: true },
transform: { react: { runtime: 'automatic' } },
},
},
exclude: /node_modules/,
},
{
test: /\.css$/,
type: 'css', // 内置 CSS 处理,无需 css-loader
},
],
},
plugins: [],
builtins: {
html: [{ template: './index.html' }], // 内置 HTML 插件
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
};
export default config;
builtin:swc-loader替代babel-loader:内置 SWC 编译,速度快数十倍type: 'css'替代style-loader+css-loader:内置 CSS 处理builtins.html替代HtmlWebpackPlugin:内置 HTML 生成
内置功能
Rspack 将很多常用的 Loader 和 Plugin 内置到 Rust 核心中,避免了 JS 插件的性能损耗:
| 内置功能 | 替代的 Webpack 插件/Loader | 说明 |
|---|---|---|
builtin:swc-loader | babel-loader + @babel/preset-* | TypeScript、JSX、装饰器编译 |
type: 'css' | style-loader + css-loader | CSS 处理与注入 |
type: 'css/module' | css-loader(modules) | CSS Modules |
builtins.html | html-webpack-plugin | HTML 模板生成 |
builtins.define | DefinePlugin | 环境变量定义 |
builtins.copy | copy-webpack-plugin | 静态资源复制 |
| 内置压缩 | terser-webpack-plugin | SWC 压缩,速度更快 |
性能数据
以一个包含 1000+ 模块的中大型 React 项目为参考:
| 指标 | Webpack 5 | Rspack | 提升倍数 |
|---|---|---|---|
| 冷启动(dev) | ~30s | ~1.5s | 约 20x |
| HMR 热更新 | ~800ms | ~50ms | 约 16x |
| 生产构建 | ~120s | ~8s | 约 15x |
| 内存占用 | ~2GB | ~500MB | 约 4x |
以上数据来源于 Rspack 官方 benchmark 及社区实测,实际性能取决于项目规模、插件数量、JS 插件占比等因素。使用越多 JS 插件,Rspack 的性能优势越小(因为需要在 Rust 和 JS 之间传递数据)。
Rspack 生态
Rspack 不仅是一个打包器,还构建了完整的工具链生态:
- Rsbuild:基于 Rspack 的开箱即用构建工具,类似 Create React App / Vite 的定位
- Rspress:基于 Rspack 的静态站点生成器,类似 VitePress
- Rslib:基于 Rspack 的库开发工具
- Modern.js:字节跳动的全栈 Web 框架,底层使用 Rspack
Farm 深入解析
什么是 Farm
Farm 是一个用 Rust 编写的极速 Web 构建工具。与 Rspack 走 Webpack 兼容路线不同,Farm 从零设计了自己的架构,提出了创新的 Partial Bundling 打包策略,旨在在 Bundle 和 Bundless 之间找到最优平衡点。
核心特性
- 极速性能:Rust 全链路实现,毫秒级 HMR
- Partial Bundling:独创的打包策略,兼顾加载性能和缓存效率
- 增量构建:模块级别的增量编译和持久化缓存
- 持久化缓存:构建结果持久化到磁盘,二次构建速度极快
- 兼容 Vite 插件:支持大部分 Vite/Rollup 插件
- 全栈支持:同时支持浏览器和 Node.js 产物
Partial Bundling 策略
Partial Bundling 是 Farm 最核心的创新,它解决了 Bundle 和 Bundless 两种方案各自的问题:
| 方案 | 代表工具 | 优点 | 缺点 |
|---|---|---|---|
| Full Bundle | Webpack | 请求数少,加载快 | 构建慢,缓存粒度粗 |
| Bundless(No Bundle) | Vite 开发模式 | 构建快,模块级缓存 | 请求数多,深层依赖瀑布流 |
| Partial Bundling | Farm | 兼顾加载和缓存 | 概念较新,生态较小 |
Partial Bundling 的核心思想:
- 按模块类型和依赖关系自动分组:将关联度高的模块打包在一起
- 控制产物数量:既不像 Bundle 那样合并为极少文件,也不像 Bundless 那样产生成百上千个请求
- 最大化缓存命中率:修改一个模块只影响其所在的 Partial Bundle,其他 Bundle 缓存仍然有效
- 并行加载:多个 Partial Bundle 可以并行请求,减少瀑布流问题
Farm 配置示例
import { defineConfig } from '@farmfe/core';
export default defineConfig({
compilation: {
input: {
index: './src/index.tsx',
},
output: {
path: 'dist',
targetEnv: 'browser', // 支持 'browser' | 'node'
},
resolve: {
extensions: ['tsx', 'ts', 'jsx', 'js'],
alias: {
'@': './src',
},
},
// Partial Bundling 配置
partialBundling: {
targetConcurrentRequests: 25, // 目标并发请求数
targetMinSize: 20 * 1024, // 最小 Bundle 大小 (20KB)
targetMaxSize: 1500 * 1024, // 最大 Bundle 大小 (1.5MB)
},
minify: true,
sourcemap: true,
},
server: {
port: 3000,
hmr: true,
},
plugins: [
'@farmfe/plugin-react', // React 支持
'@farmfe/plugin-sass', // Sass 支持
],
});
Farm vs Vite 对比
| 特性 | Vite | Farm |
|---|---|---|
| 开发模式 | Bundless(原生 ESM) | Partial Bundling |
| 生产打包 | Rollup(JS) | Farm(Rust) |
| 编译速度 | 快(esbuild 预构建) | 极快(Rust 全链路) |
| HMR 速度 | 快 | 极快(增量编译) |
| 开发/生产一致性 | 低(不同工具链) | 高(同一工具链) |
| 持久化缓存 | 无(Vite 6 实验性支持) | 内置支持 |
| 插件兼容 | Rollup 插件 | Vite/Rollup 插件 |
| 生态成熟度 | 成熟 | 较新,成长中 |
Vite 在开发模式用 ESM + esbuild,生产模式用 Rollup 打包,两套不同的工具链可能导致开发和生产环境行为不一致。Farm 在开发和生产都使用同一套 Rust 构建流程,一致性更好。
Rust 构建工具生态概览
当前 Rust 构建工具主要有四个重要项目:
| 工具 | 团队 | 定位 | Webpack 兼容 | Vite 兼容 | 成熟度 | 适用场景 |
|---|---|---|---|---|---|---|
| Rspack | 字节跳动 | Webpack 替代品 | 高 | 低 | 较成熟,已生产可用 | Webpack 项目迁移 |
| Farm | 社区 | 极速全栈构建 | 低 | 中(兼容插件) | 发展中 | 新项目、追求极致性能 |
| Rolldown | Vite 团队 | Rollup Rust 替代品 | 低 | 高(未来 Vite 内核) | 开发中 | 未来的 Vite 项目 |
| Turbopack | Vercel | Next.js 构建引擎 | 部分 | 无 | 开发中 | Next.js 项目 |
Rolldown 简介
Rolldown 是由 Vite 团队(Evan You 主导)开发的 Rust 版 Rollup,目标是成为未来 Vite 的底层构建引擎,彻底解决 Vite 开发/生产环境不一致的问题。
核心定位:
- 兼容 Rollup 插件 API
- 替代 esbuild(预构建) + Rollup(生产打包),统一为一个 Rust 工具
- 未来将作为 Vite 的核心引擎(Vite 6+ 计划)
Rolldown 仍处于活跃开发中,尚未发布稳定版本。Vite 团队计划在 Rolldown 成熟后逐步将其集成到 Vite 中,届时 Vite 将获得全链路 Rust 性能加速。
Turbopack 简介
Turbopack 是 Vercel 团队(Next.js 背后的公司)使用 Rust 开发的构建工具,其核心创新是增量计算引擎——只重新计算发生变化的部分,类似数据库的增量更新。
核心特点:
- 增量计算:函数级别的缓存和增量更新,理论上 HMR 速度与项目规模无关
- 深度集成 Next.js:目前主要作为 Next.js 的开发模式构建工具
- 不追求通用性:与 Webpack/Vite 生态兼容性低,更偏向框架专用
Turbopack 目前深度绑定 Next.js 生态,不适合作为通用构建工具使用。如果你的项目不是 Next.js,建议优先考虑 Rspack 或 Farm。
从 Webpack 迁移到 Rspack
迁移步骤
对于现有的 Webpack 项目,迁移到 Rspack 通常分为以下几步:
第一步:安装依赖
- npm
- Yarn
- pnpm
- Bun
npm install @rspack/core @rspack/cli --save-dev
yarn add @rspack/core @rspack/cli --dev
pnpm add @rspack/core @rspack/cli --save-dev
bun add @rspack/core @rspack/cli --dev
第二步:修改配置文件
将 webpack.config.ts 重命名为 rspack.config.ts,并进行以下调整:
import type { Configuration } from '@rspack/cli';
const config: Configuration = {
// 1. entry、output、resolve 等基本不用改
entry: './src/index.tsx',
output: {
path: './dist',
filename: '[name].[contenthash].js',
},
module: {
rules: [
{
test: /\.tsx?$/,
// 2. 将 babel-loader 替换为 builtin:swc-loader
use: {
loader: 'builtin:swc-loader',
options: {
jsc: {
parser: { syntax: 'typescript', tsx: true },
transform: { react: { runtime: 'automatic' } },
},
},
},
},
{
test: /\.css$/,
// 3. 使用内置 CSS 处理
type: 'css',
},
{
test: /\.module\.css$/,
type: 'css/module', // CSS Modules
},
{
test: /\.(png|jpe?g|gif|svg)$/,
type: 'asset', // 内置资源处理(等同于 asset/resource)
},
],
},
// 4. 将第三方 Plugin 替换为内置功能
builtins: {
html: [{ template: './index.html' }],
define: {
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
},
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js'],
alias: {
'@': './src',
},
},
};
export default config;
第三步:更新 package.json 脚本
{
"scripts": {
"dev": "rspack serve",
"build": "rspack build"
}
}
第四步:处理不兼容的插件
逐个检查项目中使用的 Webpack 插件,根据兼容性情况采取不同策略:
| 策略 | 适用情况 | 示例 |
|---|---|---|
| 使用内置功能替代 | 有对应内置功能 | HtmlWebpackPlugin → builtins.html |
| 直接使用 | 插件已兼容 Rspack | 大部分常见 Loader |
| 寻找替代方案 | 插件不兼容 | 使用 Rspack 社区替代插件 |
| 使用 JS 桥接 | 无替代方案 | 通过 JS 插件 API 桥接 |
迁移注意事项
迁移过程中务必注意:
- 不要一步到位:先让项目跑起来,再逐步优化(如将 babel-loader 替换为 builtin:swc-loader)
- 检查构建产物:对比迁移前后的产物,确保功能和体积没有明显差异
- 测试覆盖:确保有足够的测试用例,迁移后跑一遍完整测试
- 渐进式替换:对于不兼容的 Loader/Plugin,可以先保留 JS 版本,后续再逐步替换
何时选择 Rust 构建工具
决策建议
总结建议:
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| Webpack 大型项目,构建慢 | Rspack | 兼容性好,迁移成本低 |
| 新项目,追求极致性能 | Rsbuild 或 Farm | 开箱即用,性能最优 |
| Vite 项目,性能可接受 | 等待 Rolldown | 未来 Vite 原生升级 |
| Next.js 项目 | Turbopack(等待稳定) | 官方深度集成 |
| 库开发 | Rslib 或 Rollup | 库打包场景 |
常见面试问题
Q1: Rspack 是什么?和 Webpack 有什么关系?
答案:
Rspack 是由字节跳动开源的、使用 Rust 编写的高性能 JavaScript 打包工具。它与 Webpack 的关系可以概括为:Rspack 是 Webpack 的 Rust 高性能替代品,兼容大部分 Webpack API。
核心关系:
- API 兼容:Rspack 实现了大部分 Webpack 配置选项(entry、output、module.rules、resolve、optimization 等),配置文件结构几乎一致
- 生态兼容:支持大部分 Webpack Loader(如 css-loader、less-loader),部分 Plugin 也可直接使用
- 理念一致:采用相同的 Bundle 模式,支持相同的代码分割策略(splitChunks)
- 性能飞跃:由于 Rust 的性能优势,Rspack 的构建速度比 Webpack 快 10-20 倍
关键区别:
// Webpack:需要 babel-loader 编译 TS
{ test: /\.tsx?$/, use: 'babel-loader' }
// Rspack:内置 SWC 编译,无需外部 Loader
{ test: /\.tsx?$/, use: 'builtin:swc-loader' }
// Webpack:需要 css-loader + style-loader
{ test: /\.css$/, use: ['style-loader', 'css-loader'] }
// Rspack:内置 CSS 处理
{ test: /\.css$/, type: 'css' }
Rspack 不是 Webpack 的 fork(分叉),而是从零用 Rust 实现的全新工具,只是在 API 层面保持了 Webpack 兼容。这使得现有 Webpack 项目可以低成本迁移,同时获得数量级的性能提升。
Q2: Rust 构建工具为什么比 JavaScript 构建工具快?
答案:
Rust 构建工具的性能优势来源于多个层面:
1. 语言层面的优势
| 维度 | JavaScript (V8) | Rust |
|---|---|---|
| 执行方式 | JIT 编译,需要预热 | AOT 编译为机器码,即时达峰 |
| 内存管理 | GC 垃圾回收,有不可预测暂停 | 所有权系统,零 GC 开销 |
| 并发 | 单线程 + Worker(需序列化) | 真正多线程,共享内存 |
| 数据布局 | 对象在堆上,指针间接访问 | 栈分配 + 紧凑内存布局,cache 友好 |
2. 架构层面的优势
// JS 工具链:多个工具之间需要反复转换
const source: string = readFile('app.tsx');
const babelAST = babel.parse(source); // 第 1 次解析
const babelResult = babel.transform(babelAST); // 转换
const babelCode = babel.generate(babelResult); // 第 1 次生成代码字符串
const webpackAST = acorn.parse(babelCode); // 第 2 次解析(Webpack 内部)
const bundled = webpack.bundle(webpackAST); // 打包
const bundleCode = webpack.generate(bundled); // 第 2 次生成代码字符串
const terserAST = terser.parse(bundleCode); // 第 3 次解析
const minified = terser.minify(terserAST); // 压缩,第 3 次生成代码字符串
// 同一份代码被解析了 3 次、生成了 3 次!
// Rust 工具:全链路共享 AST,只解析一次
const ast = rust_parse('app.tsx'); // 只解析 1 次
rust_transform(ast); // 原地转换(零拷贝)
rust_bundle(ast); // 直接操作 AST 打包
rust_minify(ast); // 直接压缩
const output = rust_generate(ast); // 只生成 1 次代码
3. 并行化能力
Rust 的所有权系统允许安全地在多个线程间共享数据,使得构建的各个阶段可以充分并行:
- 文件解析并行:多个文件同时解析
- 转换并行:多个模块同时进行代码转换
- 代码生成并行:多个 chunk 同时生成最终代码
综合以上因素,Rust 构建工具可以实现 10-100 倍的性能提升。
Q3: 目前的 Rust 构建工具生态是怎样的?如何选择?
答案:
目前 Rust 构建工具生态有四大主力:
| 工具 | 背后团队 | 核心策略 | 适用场景 | 稳定性 |
|---|---|---|---|---|
| Rspack | 字节跳动 | Webpack 兼容 | 存量 Webpack 项目迁移 | 生产可用 |
| Farm | 社区驱动 | Partial Bundling | 新项目、追求极致性能 | 可用,持续完善 |
| Rolldown | Vite 团队 | Rollup Rust 替代 | 未来 Vite 生态 | 开发中 |
| Turbopack | Vercel | 增量计算 | Next.js 项目 | 开发中 |
选择建议:
- 现有 Webpack 项目想提速 → 选 Rspack,迁移成本最低,API 高度兼容
- 新项目,想开箱即用 → 选 Rsbuild(基于 Rspack)或 Farm
- 正在用 Vite,性能还行 → 等 Rolldown,未来 Vite 会自动升级底层引擎
- Next.js 项目 → 关注 Turbopack,等官方稳定支持
- 需要稳定的生产环境 → 目前 Rspack 成熟度最高,字节内部大规模使用验证
回答这类生态问题时,可以补充一个趋势判断:前端构建工具正在经历从 JavaScript → Go/Rust 混合 → 全 Rust 的演进过程。esbuild(Go)和 SWC(Rust)解决了编译/转译环节的性能问题,而 Rspack、Farm、Rolldown、Turbopack 则要解决整个构建流程的性能问题。最终目标是实现全链路 Rust,消除跨语言通信开销。