跳到主要内容

Rspack 与 Farm:Rust 构建工具

问题

Rspack 和 Farm 分别是什么?为什么前端社区在向 Rust 构建工具迁移?它们与 Webpack、Vite 有什么关系?当前 Rust 构建工具生态是怎样的?

答案

RspackFarm 是新一代基于 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?

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 兼容:支持 loaderpluginmoduleresolveoptimization 等核心配置
  • 内置 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 高度相似,迁移成本极低:

webpack.config.ts
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;
rspack.config.ts
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;
关键差异
  1. builtin:swc-loader 替代 babel-loader:内置 SWC 编译,速度快数十倍
  2. type: 'css' 替代 style-loader + css-loader:内置 CSS 处理
  3. builtins.html 替代 HtmlWebpackPlugin:内置 HTML 生成

内置功能

Rspack 将很多常用的 Loader 和 Plugin 内置到 Rust 核心中,避免了 JS 插件的性能损耗:

内置功能替代的 Webpack 插件/Loader说明
builtin:swc-loaderbabel-loader + @babel/preset-*TypeScript、JSX、装饰器编译
type: 'css'style-loader + css-loaderCSS 处理与注入
type: 'css/module'css-loader(modules)CSS Modules
builtins.htmlhtml-webpack-pluginHTML 模板生成
builtins.defineDefinePlugin环境变量定义
builtins.copycopy-webpack-plugin静态资源复制
内置压缩terser-webpack-pluginSWC 压缩,速度更快

性能数据

以一个包含 1000+ 模块的中大型 React 项目为参考:

指标Webpack 5Rspack提升倍数
冷启动(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 BundleWebpack请求数少,加载快构建慢,缓存粒度粗
Bundless(No Bundle)Vite 开发模式构建快,模块级缓存请求数多,深层依赖瀑布流
Partial BundlingFarm兼顾加载和缓存概念较新,生态较小

Partial Bundling 的核心思想:

  1. 按模块类型和依赖关系自动分组:将关联度高的模块打包在一起
  2. 控制产物数量:既不像 Bundle 那样合并为极少文件,也不像 Bundless 那样产生成百上千个请求
  3. 最大化缓存命中率:修改一个模块只影响其所在的 Partial Bundle,其他 Bundle 缓存仍然有效
  4. 并行加载:多个 Partial Bundle 可以并行请求,减少瀑布流问题

Farm 配置示例

farm.config.ts
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 对比

特性ViteFarm
开发模式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社区极速全栈构建中(兼容插件)发展中新项目、追求极致性能
RolldownVite 团队Rollup Rust 替代品高(未来 Vite 内核)开发中未来的 Vite 项目
TurbopackVercelNext.js 构建引擎部分开发中Next.js 项目

Rolldown 简介

Rolldown 是由 Vite 团队(Evan You 主导)开发的 Rust 版 Rollup,目标是成为未来 Vite 的底层构建引擎,彻底解决 Vite 开发/生产环境不一致的问题。

核心定位:

  • 兼容 Rollup 插件 API
  • 替代 esbuild(预构建) + Rollup(生产打包),统一为一个 Rust 工具
  • 未来将作为 Vite 的核心引擎(Vite 6+ 计划)
Rolldown 现状

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 install @rspack/core @rspack/cli --save-dev

第二步:修改配置文件

webpack.config.ts 重命名为 rspack.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 脚本

package.json
{
"scripts": {
"dev": "rspack serve",
"build": "rspack build"
}
}

第四步:处理不兼容的插件

逐个检查项目中使用的 Webpack 插件,根据兼容性情况采取不同策略:

策略适用情况示例
使用内置功能替代有对应内置功能HtmlWebpackPlugin → builtins.html
直接使用插件已兼容 Rspack大部分常见 Loader
寻找替代方案插件不兼容使用 Rspack 社区替代插件
使用 JS 桥接无替代方案通过 JS 插件 API 桥接

迁移注意事项

重要提醒

迁移过程中务必注意:

  1. 不要一步到位:先让项目跑起来,再逐步优化(如将 babel-loader 替换为 builtin:swc-loader
  2. 检查构建产物:对比迁移前后的产物,确保功能和体积没有明显差异
  3. 测试覆盖:确保有足够的测试用例,迁移后跑一遍完整测试
  4. 渐进式替换:对于不兼容的 Loader/Plugin,可以先保留 JS 版本,后续再逐步替换

何时选择 Rust 构建工具

决策建议

总结建议:

场景推荐方案理由
Webpack 大型项目,构建慢Rspack兼容性好,迁移成本低
新项目,追求极致性能RsbuildFarm开箱即用,性能最优
Vite 项目,性能可接受等待 Rolldown未来 Vite 原生升级
Next.js 项目Turbopack(等待稳定)官方深度集成
库开发Rslib 或 Rollup库打包场景

常见面试问题

Q1: Rspack 是什么?和 Webpack 有什么关系?

答案

Rspack 是由字节跳动开源的、使用 Rust 编写的高性能 JavaScript 打包工具。它与 Webpack 的关系可以概括为:Rspack 是 Webpack 的 Rust 高性能替代品,兼容大部分 Webpack API

核心关系:

  1. API 兼容:Rspack 实现了大部分 Webpack 配置选项(entry、output、module.rules、resolve、optimization 等),配置文件结构几乎一致
  2. 生态兼容:支持大部分 Webpack Loader(如 css-loader、less-loader),部分 Plugin 也可直接使用
  3. 理念一致:采用相同的 Bundle 模式,支持相同的代码分割策略(splitChunks)
  4. 性能飞跃:由于 Rust 的性能优势,Rspack 的构建速度比 Webpack 快 10-20 倍

关键区别:

从 Webpack 迁移到 Rspack 的配置变化
// 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 构建工具的性能瓶颈
// 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 构建工具的高效流程
// 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新项目、追求极致性能可用,持续完善
RolldownVite 团队Rollup Rust 替代未来 Vite 生态开发中
TurbopackVercel增量计算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,消除跨语言通信开销。

相关链接