Rolldown 是一个用 Rust 编写的现代 JavaScript 打包工具,旨在提供极致的性能和出色的开发体验。它继承了 Rollup 的设计理念和插件 API,同时通过 Rust 的性能优势实现了显著的速度提升,目标是成为 Vite 未来的底层打包引擎。
核心特性
- 🚀 极致性能:基于 Rust 和多线程并行架构,打包速度相比基于 JavaScript 的工具可提升一个数量级。
- 🔄 Rollup 兼容:API 设计与 Rollup 高度一致,特别是插件钩子,使得生态迁移成本更低。
- 📦 功能内置:默认支持 TypeScript、JSX、模块解析、CommonJS 转换和代码压缩,无需繁琐的插件配置。
- 🔧 现代化工具链:为现代 Web 开发而生,支持 Tree Shaking、代码分割、热模块替换(HMR)等。
- 🎯 开发友好:提供清晰的错误信息和调试支持。
为什么选择 Rolldown?
实现原因和技术优势
-
性能瓶颈的解决 传统的 JavaScript 工具链受限于 Node.js 的性能瓶頸:
- 单线程限制:JavaScript 的事件循环模型不擅长 CPU 密集型的并行任务。
- 内存开销:高昂的垃圾回收(GC)成本和重复的抽象语法树(AST)解析。
Rolldown 通过 Rust 从根本上解决这些问题:
Rust
arduino// Rust 的 Rayon 库可以轻松实现数据并行处理 use rayon::prelude::*; modules.par_iter().for_each(|module| { // 在多个线程上并行处理模块 process_module(module); });
-
内存安全和零成本抽象
- 内存安全:Rust 的所有权和借用检查机制在编译时就能防止内存泄漏和数据竞争问题。
- 零成本抽象:Rust 的高级语言特性(如迭代器、闭包)在编译后几乎没有运行时开销。
-
与现有生态系统的兼容性
- 兼容 Rollup 插件 API,允许现有插件通过适配层或少量修改即可运行。
- 内置与 Node.js 兼容的模块解析算法。
安装和基础使用
安装
Rolldown 提供一个命令行工具(CLI)和一个编程式 API 库。
Bash
bash
# 使用 npm 安装 CLI
npm install -D @rolldown/cli
# 使用 pnpm
pnpm add -D @rolldown/cli
# 使用 yarn
yarn add -D @rolldown/cli
# 如果需要通过 Node.js 脚本调用,安装核心库
npm install -D rolldown
基础用法
-
命令行使用
Bash
r# 基础打包,Rolldown 会自动寻找入口文件(如 src/index.js) rolldown # 使用配置文件进行打包 rolldown -c # 指定一个不同的配置文件 rolldown --config rolldown.config.ts # 开启监听(Watch)模式 rolldown -w
-
编程式使用
JavaScript
javascript// build.js import { rolldown } from 'rolldown' import path from 'node:path' async function build() { const bundle = await rolldown({ input: path.resolve(import.meta.dirname, 'src/index.js'), output: { dir: 'dist', format: 'es', }, }) await bundle.write() } build()
配置详解
配置文件(默认为 rolldown.config.js
或 .ts
)提供了更灵活的控制。
基础配置结构
JavaScript
perl
// rolldown.config.js
export default {
// 入口文件
input: 'src/index.js',
// 输出配置
output: {
dir: 'dist',
format: 'es', // 'es', 'cjs'
sourcemap: true,
// 内置压缩功能,取代 Terser 插件
minify: true,
},
// 外部依赖,这些模块不会被打包进去
external: ['react', 'react-dom'],
// Rolldown 旨在兼容 Rollup 插件
plugins: [
// ... 自定义或社区插件
],
// 内置强大的模块解析功能
resolve: {
alias: {
'@': './src',
'utils': './src/utils',
},
// Rolldown 默认会处理这些扩展名,无需配置
// extensions: ['.js', '.ts', '.jsx', '.tsx']
},
};
多入口配置
JavaScript
css
export default {
input: {
main: 'src/index.js',
admin: 'src/admin.js',
},
output: {
dir: 'dist',
format: 'es',
// 使用占位符定义输出文件名格式
entryFileNames: 'entry-[name]-[hash].js',
chunkFileNames: 'chunks/[name]-[hash].js',
},
};
条件配置
可以导出一个函数,根据命令行参数动态生成配置。
JavaScript
dart
export default (commandLineArgs) => {
// commandLineArgs.watch 可以判断是否处于监听模式
const isDev = commandLineArgs.w || commandLineArgs.watch;
return {
input: 'src/index.js',
output: {
dir: 'dist',
format: 'es',
// 开发模式生成 SourceMap,生产模式不生成
sourcemap: isDev,
// 生产模式开启压缩
minify: !isDev,
},
};
};
与 Rollup 对比
性能对比(预期目标)
特性 | Rollup (JavaScript) | Rolldown (Rust) | 提升幅度(目标) |
---|---|---|---|
冷启动时间 | ~2.5s | ~0.3s | ~8x |
增量构建 | ~1.2s | ~0.1s | ~12x |
大型项目构建 | ~45s | ~4.5s | ~10x |
内存使用 | 较高 | 显著降低 | ~2-3x |
导出到 Google 表格
配置理念对比
Rolldown 的核心优势是 功能内置,从而简化配置。
一个典型的 Rollup 配置:
JavaScript
javascript
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
import terser from '@rollup/plugin-terser';
export default {
input: 'src/index.js',
output: { /* ... */ },
plugins: [
resolve(), // 解析 node_modules
commonjs(), // 转换 CJS 到 ESM
babel({ presets: ['@babel/preset-env'] }), // JS 编译
terser() // 代码压缩
],
external: ['react']
};
等效的 Rolldown 配置:
JavaScript
dart
// rolldown.config.js
export default {
input: 'src/index.js',
output: {
/* ... */
minify: true, // 内置压缩
},
// 解析、CJS 转换、TypeScript/ESNext 语法编译都是内置的
// 只有当需要特定的 Babel 插件时才需要引入 Babel
external: ['react']
};
从 Rollup 迁移到 Rolldown
迁移的核心是 移除不再需要的插件,并调整配置以使用 Rolldown 的内置功能。
注意:目前没有官方的自动迁移工具 (@rolldown/migrate
),迁移需要手动进行。
迁移步骤
- 备份 :备份你现有的
rollup.config.js
和package.json
。 - 安装依赖 :安装
@rolldown/cli
。 - 创建新配置 :创建一个
rolldown.config.js
文件。 - 迁移核心配置 :将
input
、output
(注意minify
选项)、external
等核心配置拷贝过来。 - 处理插件:根据下面的兼容性列表,移除或替换原有插件。
- 更新
package.json
:将构建脚本从rollup -c
修改为rolldown -c
。 - 测试:运行构建命令,检查输出是否符合预期。
插件兼容性与替代方案
Rollup 插件 | Rolldown 中的状态 | 建议操作 |
---|---|---|
@rollup/plugin-node-resolve |
❌ 不需要 | 移除。功能已内置且默认开启。 |
@rollup/plugin-commonjs |
❌ 不需要 | 移除。功能已内置且默认开启。 |
@rollup/plugin-typescript |
❌ 不需要 | 移除。原生支持 TypeScript 和 tsconfig.json。 |
@rollup/plugin-babel |
⚠️ 部分需要 | 如果只用于编译 TS/JSX 或新版 JS 语法,移除 。如果需要特定的 Babel 插件(如 babel-plugin-macros ),则保留。 |
@rollup/plugin-terser |
❌ 不需要 | 移除。使用内置的 output.minify: true 选项。 |
rollup-plugin-vue / svelte |
⚠️ 需要适配 | 特定框架的插件需要等待官方或社区提供 Rolldown 的原生版本或适配层。 |
@rollup/plugin-replace |
✅ 功能可用 | 可以继续使用,或等待 Rolldown 可能提供的内置 define 选项(类似 Vite)。 |
导出到 Google 表格
插件系统
Rolldown 的目标是与 Rollup 的插件 API 保持高度兼容,让你能利用现有的生态或轻松编写自己的插件。
插件开发基础
插件是一个返回特定结构对象的函数,通过钩子(Hook)在构建过程的不同阶段介入。
JavaScript
javascript
// my-virtual-plugin.js
export function virtualModulePlugin(modules) {
const prefix = 'virtual:';
return {
name: 'virtual-module-plugin', // 插件名称,用于调试
// 解析钩子:解析模块 ID
resolveId(id) {
if (id.startsWith(prefix)) {
return id; // 如果是我们处理的模块,直接返回 ID
}
},
// 加载钩子:提供模块内容
load(id) {
if (id.startsWith(prefix)) {
const moduleName = id.slice(prefix.length);
return modules[moduleName] || `export const msg = "Module not found"`;
}
},
// 转换钩子:转换模块代码
transform(code, id) {
if (id.endsWith('.txt')) {
return {
code: `export default ${JSON.stringify(code)}`,
map: null // 可选,SourceMap
};
}
}
};
}
// rolldown.config.js
import { virtualModulePlugin } from './my-virtual-plugin.js';
export default {
input: 'src/index.js',
plugins: [
virtualModulePlugin({
'config': 'export default { apiKey: "12345" }'
})
]
};
在代码中可以这样使用:import config from 'virtual:config';
性能优化
构建性能优化
Rolldown 的核心优势就是性能,大部分优化是自动的。未来可能会提供更细粒度的控制。
JavaScript
arduino
// 示例:未来可能支持的配置
export default {
// 注意:这些 API 是推测性的,请以官方文档为准
experimental: {
// 显式开启并行处理(通常默认开启)
parallel: true,
},
cache: {
// 启用文件系统缓存以加速二次构建
dir: 'node_modules/.rolldown_cache',
}
}
输出产物优化
通过 output
配置对生成的文件进行优化。
JavaScript
arduino
export default {
output: {
dir: 'dist',
format: 'es',
// 使用 hash 命名,利于长期缓存
entryFileNames: 'assets/[name].[hash].js',
chunkFileNames: 'assets/[name].[hash].js',
// 配置内置压缩器
minify: true, // 等同于 output.minify: {}
}
}
最佳实践
项目结构建议
bash
project/
├── src/
│ ├── index.js # 主入口
│ ├── components/ # 组件
│ └── lib/ # 库代码
├── dist/ # 构建输出目录
├── rolldown.config.js # Rolldown 配置文件
├── package.json
└── tsconfig.json # TypeScript 配置文件
多环境配置
在 package.json
中定义不同的构建脚本。
JSON
json
// package.json
"scripts": {
"dev": "rolldown -c -w --environment MODE:development",
"build": "rolldown -c --environment MODE:production",
"build:analyze": "rolldown -c --environment MODE:production,ANALYZE:true"
}
在配置文件中读取这些环境变量。
JavaScript
arduino
// rolldown.config.js
const { MODE, ANALYZE } = process.env;
const isDev = MODE === 'development';
export default {
input: 'src/index.js',
output: {
dir: 'dist',
sourcemap: isDev,
minify: !isDev,
},
plugins: [
// 条件式地添加插件
ANALYZE === 'true' && bundleAnalyzerPlugin()
].filter(Boolean)
};
调试和错误处理
Rolldown 提供了详细的钩子来处理警告和错误。
JavaScript
javascript
export default {
// 构建过程中的警告处理
onwarn(warning, warn) {
// 忽略特定的警告 (例如,关于 'this' 的警告)
if (warning.code === 'THIS_IS_UNDEFINED') return;
// 将警告打印到控制台
warn(warning);
},
}
总结
Rolldown 代表了 JavaScript 构建工具的未来方向:用高性能的系统语言重写核心逻辑,同时保持与现有生态的兼容性。
选择 Rolldown 的理由:
- 无与伦比的性能:为大型项目带来数量级的构建速度提升。
- 简化的配置:内置常用功能,告别繁琐的插件组合。
- 熟悉的用户体验:与 Rollup 相似的配置和插件 API,学习曲线平缓。
随着它在 Vite 等项目中逐步落地,Rolldown 必将成为前端工具链中不可或缺的一环。建议从现在开始关注它,并在非关键项目中尝试使用,体验下一代构建工具的魅力。