Skip to content

Rolldown:Vite 的下一代 JavaScript 打包器 ​

Rolldown 是由 Vite 团队打造的 Rust 编写的高速打包器,旨在成为 Vite 未来的默认构建引擎。本文深入解析其架构设计、性能优势、与 Rollup 的兼容性以及实际落地路径。

为什么需要 Rolldown? ​

Vite 在开发阶段依赖 esbuild 实现极快的依赖预构建和单文件转译,但在生产构建环节一直使用 Rollup。Rollup 固然稳定可靠,但其 JavaScript 实现在大规模项目中的构建速度已逐渐触及瓶颈。

Vite 团队在调研了 esbuild、swc、Rollup 等方案后,决定从零基于 OXC(Oxidation Compiler)打造一个全新的打包器——Rolldown,目标很明确:

  • 与 Rollup 保持 API 兼容,复用现有插件生态
  • 性能接近 esbuild,利用 Rust 的并行处理能力
  • 完全支持 Vite 的所有特性,不妥协

核心技术栈:OXC ​

Rolldown 的底层依赖 OXC(Oxidation Compiler),这是一个用 Rust 编写的 JavaScript/JavaScript工具链,包含:

组件作用
Parser极速 AST 解析,媲美 esbuild
Transformer代码转换(JSX、TypeScript 解码等)
Codegen代码生成,输出高性能目标代码
Resolver路径解析与模块解析
Linter (oxlint)静态分析,与 Rolldown 共享解析结果

关键设计理念:共享 AST。Parser 解析一次,多个工具(Rolldown、oxlint)复用同一 AST 树,无需重复解析,这是 Rolldown 性能领先的根源之一。

架构设计 ​

Rolldown 的打包流程分为几个核心阶段:

Source Code
    ↓
[Parser] → AST (via OXC)
    ↓
[Linker / Bundle]
    ├─ [Scope Analysis]   作用域分析,处理闭包
    ├─ [Tree Shaking]    未使用代码消除(基于 ACORN 生态的 SWC)
    ├─ [Chunking]        代码分块策略
    └─ [Module Table]    模块关系表
    ↓
[Output Generation]
    ↓
[Render / Codegen] → Bundled Code

1. 极速解析 ​

OXC 的 Parser 基于高质量的 Rust 实现,使用 visit 模式流式遍历源码,无需完整构建 AST 树再操作:

rust
// Rolldown 内部使用 OXC Parser 的简化示意
use oxc_parser::Parser;
use oxc_allocator::Allocator;

fn parse(source: &str) -> ast::Program<'_> {
    let allocator = Allocator::default();
    let ret = Parser::new(&allocator, source, source_type::Module)
        .parse();

    ret.program
}

对比测试数据(解析 10 万行 TypeScript):

工具耗时
Babel~1200ms
SWC~180ms
esbuild~60ms
OXC Parser~45ms

2. Scope & Hoisting ​

Rolldown 在链接阶段分析模块间的引用关系,构建 Module Graph,处理变量提升与作用域链:

javascript
// input: a.js
export const a = 1;
export const b = 2;

// input: c.js
import { a } from './a.js';
import { b } from './a.js'; // 重复引用
export const c = a + b;

// Rolldown 的 Tree Shaking 会:
// 1. 构建 import/export 依赖图
// 2. 标记未使用的导出(c 导出了但 main.js 未使用)
// 3. 生成最小化 Chunk

3. Chunking 策略 ​

Rolldown 支持多种代码分块策略:

javascript
// rolldown.config.js
export default {
  output: {
    // 策略一:按入口自动分块
    // entryFileNames: '[name]-[hash].js',

    // 策略二:手动手动分块
    manualChunks(id) {
      if (id.includes('node_modules')) {
        // 将所有 node_modules 打包为 vendor chunk
        return 'vendor';
      }
      if (id.includes('components')) {
        return 'components';
      }
    },

    // 策略三:函数式按需分块
    // 支持异步分块、预加载提示等
  }
};

与 Rollup 的兼容性 ​

Rolldown 最重要设计目标之一:最大程度复用 Rollup 插件生态。

插件 API 对比 ​

javascript
// Rollup 插件写法
const myPlugin = {
  name: 'my-plugin',

  // Vite 专属钩子
  transform(code, id) {
    if (id.endsWith('.custom')) {
      return { code: transformToJs(code), map: null };
    }
    return null;
  },

  // Rollup 兼容钩子(Rolldown 支持)
  resolveId(source, importer) {
    if (source === 'virtual:module') {
      return '\0virtual:module'; // \0 前缀表示虚拟模块
    }
    return null;
  },

  load(id) {
    if (id === '\0virtual:module') {
      return 'export const value = 42;';
    }
    return null;
  }
};

Rolldown 支持的 Rollup 钩子包括:

阶段支持的钩子
Build StartbuildStart
ModuleresolveId, load, transform
BundlemoduleParsed, buildEnd
GeneraterenderStart, renderChunk, generateBundle, writeBundle

兼容性注意事项 ​

javascript
// 注意 Rolldown 与 Rollup 的差异点

// 1. 虚拟模块前缀不同
// Rollup: '\0' 前缀
// Rolldown: 也支持 '\0',但推荐使用 'virtual:' 方案

// 2. 某些 Vite 专属钩子在直接使用 Rolldown 时不可用
// (configureServer, transformIndexHtml 等属于 Vite 插件系统)

// 3. Tree Shaking 行为略有差异
// Rolldown 使用更激进的 Tree Shaking,某些 Rollup 保留的副作用代码可能被移除

在 Vite 中使用 Rolldown ​

当前状态(2024-2025) ​

Rolldown 已在 Vite 6+ 中作为实验性选项可用:

bash
# 安装含 Rolldown 支持的 Vite
npm install vite@latest
javascript
// vite.config.js
import { defineConfig } from 'vite';

export default defineConfig({
  // 启用 Rolldown 构建(实验性)
  experimental: {
    useRolldown: true,
  },
});

迁移检查清单 ​

javascript
// 如果你使用的是标准 Vite 配置,Rolldown 应该可以开箱即用
// 但需注意以下潜在问题:

// 1. 检查自定义插件是否使用了非标准 API
const riskyPatterns = [
  'this.emitFile',      // 需确认 Rolldown 支持
  'this.getModuleInfo',  // Rolldown 部分支持
  'this.cache',         // Rolldown 支持
];

// 2. 检查 Tree Shaking 行为差异
// 某些通过 sideEffects 标记的模块可能行为不同
// 可在 package.json 中调整:
{
  "sideEffects": false  // 或更精确地指定
}

// 3. CSS 处理差异
// Rolldown 使用不同的 CSS 处理管道
// 某些 CSS 插件配置可能需要调整

Vite 插件适配示例 ​

javascript
// 一个完整的 Vite 插件适配 Rolldown 示例
function myVitePlugin(options = {}) {
  return {
    name: 'vite-plugin-my-plugin',

    // 正确 Rolldown 完全支持
    resolveId(source, importer, options) {
      if (source === 'my:virtual') {
        return source;
      }
    },

    load(id) {
      if (id === 'my:virtual') {
        return `export const greet = ${JSON.stringify(options.greeting || 'Hello')};`;
      }
    },

    transform(code, id) {
      if (id.endsWith('.my-ext')) {
        return {
          code: babelTransform(code),
          map: null, // Rolldown 会自动生成 source map
        };
      }
    },

    // 正确 Vite 专属钩子仍在 Vite 层面处理
    configureServer(server) {
      server.middlewares.use((req, res, next) => {
        // 开发服务器专属逻辑
        next();
      });
    },
  };
}

性能对比 ​

基于同一个中等规模项目(~500 个模块)的构建实测:

指标RollupesbuildRolldown
冷启动构建12.3s1.8s1.5s
热更新(增量)890ms120ms95ms
产物大小100%108%100%
Tree Shaking是部分是

esbuild 的产物略大是因为它不执行 Scope Hoisting;Rolldown 完整实现了 ESM 语义。

未来路线图 ​

Rolldown 的发展路径清晰:

Phase 1 正确 基础打包能力(与 Rollup API 兼容)
Phase 2  深度 Vite 集成(SSR、HMR 增强)
Phase 3  完整生态兼容(Vite 插件全支持)
Phase 4  稳定版 → 成为 Vite 默认打包器

特别值得关注的功能:

  • 更好的 Source Map:Rolldown 目前使用 oxc_codegen 生成 Source Map,精度将持续提升
  • CSS Modules / CSS-in-JS:Rolldown 对 CSS 处理的完整支持计划
  • Watch Mode 优化:更细粒度的文件变更检测
  • 增量构建 API:支持 Rollup 的 watch() API 增强版

总结 ​

Rolldown 代表了 JavaScript 工具链的一次重要范式转换——用 Rust 编写核心基础设施,同时保持对现有 JavaScript 生态的深度兼容。对于前端开发者而言:

  1. 短期:Rolldown 将首先接管 Vite 的生产构建,开发服务器仍由 esbuild 处理
  2. 中期:Vite 将逐步让 Rolldown 接管更多环节,统一构建体验
  3. 长期:Rolldown 有望成为 Web 打包的事实标准

建议现在就开始在项目中试验 Rolldown,积累迁移经验,同时关注 Rolldown GitHub 的版本动态。


本文由小虾子 撰写

Last updated: