Skip to main content

Rolldown 与 Vite 8 新架构

Vite 长期存在「dev 用 esbuild、build 用 Rollup」的双引擎问题。Vite 8 用 Rolldown 统一了两者。

一、dev 与 build 行为不一致​

早期 Vite 的架构是一个务实取舍:dev 用 esbuild 做转换(快),build 用 Rollup 做打包(产物好)。它换来了开发体验,代价是两套工具、两套插件行为、两套 tree shaking 实现。

由此催生了一类几乎每个 Vite 用户都遇到过的 bug:dev 一切正常,构建后报错。不是代码写错了,是两个引擎对同一段代码的处理不一致——比如某个 CJS 依赖在 dev 里被正确转换,在构建里走了另一条路径。

这个坑的特殊之处在于:它在开发阶段完全不可见,只在发布前才暴露,而那时候往往是最紧张的时候。这也是统一打包器最直接的动因。

Vite 7:两套引擎dev:esbuild 做转换build:Rollup 打包两套插件、两套 tree shakingVite 8:一套引擎Rolldown 同时管 dev 与 buildOxc 负责语法转换行为一致,插件只需一套
图:Vite 8 的核心变化不是「更快」,而是 dev 与 build 终于用同一个引擎

二、Rust 写的统一打包器​

Rolldown 是用 Rust 重写的打包器,兼容 Rollup 的插件 API——这是它最关键的设计决策:现有的 Rollup / Vite 插件生态可以平移过来,而不是从头重建。

时间线(截至 2026 年 10 月):

  • 2026 年 3 月 —— Vite 8 发布,Rolldown 成为 dev 与 build 的统一打包器(Vite 7 时期只能通过单独的 rolldown-vite 包预览);
  • 2026 年 5 月 —— Rolldown 1.0 发布,公开 API 按语义化版本锁定。

同时,Vite 8 里的转换层也换了:Oxc(Rust 写的解析器、转换器、压缩器)接替了原本 esbuild 承担的那部分工作。

一句话定位:Rolldown 是「用 Rust 重写的 Rollup」,而 Rspack 是「用 Rust 重写的 webpack」。两者不是竞争关系,它们面向不同的迁移起点——从 Rollup/Vite 来就用 Rolldown,从 webpack 来就用 Rspack。

三、一致性与构建速度​

速度是最显眼的一层:官方公布的数据是比 Rollup 快 10~30 倍,量级随项目规模增长而拉大。但更值得强调的是第二层:

一致性——同一个打包器、同一套插件 API、同一份 tree shaking 规则。这意味着「dev 能跑、build 报错」这一整类问题从机制上被消除。你在开发时验证过的东西,就是你会发布的东西。

还有一个常被忽略的收益:CI 上的改善往往比本地更明显。因为 CI 机器的磁盘更慢、CPU 缓存更少,而这正是 Rust 单趟打包最能拉开差距的条件。

四、迁移时要留意的​

这一节是实操重点,按踩坑概率排序:

① 配置项改名。 build.rollupOptions 改成 build.rolldownOptions;manualChunks 由 codeSplitting.groups 取代(注意写在 output 下面);旧写法在新版里可能被静默忽略,迁移时以官方升级指南为准。这两项覆盖了大部分配置改动。

// 旧
build: { rollupOptions: { output: { manualChunks: { vendor: ['react'] } } } }
// 新
build: { rolldownOptions: { output: { codeSplitting: { groups: [{ name: 'vendor', test: /react/ }] } } } }

② CJS 互操作是最常见的运行时破坏。 依赖 CommonJS 的项目容易在这里出问题。排查时可以用兼容开关作为临时过渡,同时把 CJS 依赖的改造排进计划——开关是止血,不是治疗。

③ Yarn PnP 用户会被阻塞。 Rolldown 的模块解析是原生 Rust 实现,没法像 Node 的 require 那样被 PnP 打补丁。使用 PnP 的项目需要先切回 node-modules 链接方式。

④ 内存占用上升。 Vite 8 在 dev 下的内存开销明显高于上一代(官方已将其列为已知问题并在优化)。CI runner 内存紧张(比如 2GB 以下)时要留意。

⑤ 产物行为要回归。 即使构建成功,也要比对产物内容——死代码消除、分块策略这类行为的细微变化,可能只在运行时才显现。一个低成本的回归手段,是切换前后各出一份产物、比体积与文件清单:

// 比对两次产物体积差异的简单脚本(回归验证用)
import { readdirSync, statSync } from 'node:fs'
function sizeOf(dir) {
return readdirSync(dir).reduce((s, f) => s + statSync(`${dir}/${f}`).size, 0)
}
console.log('webpack:', sizeOf('dist-webpack'), 'rspack:', sizeOf('dist-rspack'))

体积一致还不够,导出不一致才是最危险的那类回归:

# 比对两次构建的导出清单
node -e "import('./dist/index.js').then(m => console.log(Object.keys(m).sort().join('\n')))" > after.txt
diff before.txt after.txt && echo "导出一致"

# 再跑一次冒烟,确认副作用(样式注入、全局注册)没丢
node --input-type=module -e "import('./dist/index.js'); console.log('ok')"

五、什么项目该升级​

按现状分三类:

  • 新项目 —— 直接用 Vite 8,没有理由从旧版本起步;
  • Vite 7 的标准 ESM 项目 —— 建议升级,配置改动集中在上面两处,多数项目半天能完成;
  • 重度依赖 CJS、或使用 Yarn PnP —— 可以缓一个版本,先把依赖问题处理掉再迁。

不建议的理由只有一条:收益不足以覆盖回归成本。速度不是唯一考量,尤其当项目发布节奏紧张、没有余量做产物回归时,暂缓是合理的。

一个降低风险的做法是两步走:先在 Vite 7 上用 rolldown-vite 单独验证打包器,确认产物没问题后再升 Vite 8——这样能把「打包器问题」和「API 变更问题」分开排查。

// vite 7 上用 rolldown-vite 单独验证打包器(两步走的第一步)
import { defineConfig } from 'rolldown-vite'
export default defineConfig({
// 现有配置基本不变,只把打包器换成 Rolldown
})

dev 与 build 行为是否真的对齐,最简单的验证是同一份代码两边各跑一次:

// 在 dev 与 preview 下各执行一次,输出应当完全一致
import { heavyCompute } from './heavy.js'
console.log(heavyCompute(20))

// 若 dev 正常而 build 后抛错,最常见的原因是 CJS 互操作:
// 默认导出在两种模式下解析方式不同,改用命名导入通常能绕过

六、不只是换了个打包器​

Vite 7 并没有默认使用 Rolldown,那时只能单独预览;Vite 8(2026-03)才统一,Rolldown 1.0 随后于 2026-05 发布。截至 2026 年 10 月,升级前建议先核对自己所用版本的情况。

升级也不只影响构建速度——死代码消除、分块策略这些产物行为可能跟着变,必须做回归。

老项目更不该立刻升:按插件兼容性和 CJS 依赖情况评估,收益不够时暂缓更稳。

至于 Rolldown 和 Rspack,它们不是竞品:一个兼容 Rollup 的 API,一个兼容 webpack 的 API,面向的是不同的迁移路径。

这次换引擎最值钱的不是快了多少,而是「你在 dev 里验证过的东西,就是你会发布的东西」。

Rolldown 的进度与兼容范围以 rolldown.rs 为准,这块变化快,判断能不能上生产别看半年前的评测。