首页 / 文章 / Vite 8将其打包工具合并到了Rolledown中——这导致了什么问题?

Vite 8将其打包工具合并到了Rolledown中——这导致了什么问题?

Vite 8 在开发环境和生产环境默认采用滚降策略。真正的 CJS 互操作性问题、代码块迁移的隐患,以及在确认 CI 测试通过前需检查的安全事项。

1296 词

多年来,Vite暗中使用了两种不同的打包工具——一种用于开发阶段,另一种用于发布阶段。Rolldown结束了这种分离状态。速度提升是实实在在的,出现问题的情况也同样真实。

许多团队都了解这些症状,但却说不出根本原因:本地服务器状态正常,生产环境却出现问题,而根源并非拼写错误。用于开发时提供模块的运行时与用于生产环境打包模块的工具链在处理某些边缘情况时存在分歧。在Vite中,这种分歧是结构性的:esbuild负责开发阶段的转换,Rollup则负责生产环境的打包,而两者之间的衔接足够良好,使得问题暂时不可见——直到最终暴露出来。

Vite 8通过一个Rust打包工具Rolldown消除了这种分歧。基准测试结果显示其性能优异,那些因多年双引擎机制带来的问题而出故障的应用列表也证明了这一点。只有了解问题的两面,才能在升级过程中避免意外状况的发生。

Vite 8 中有哪些变化

2020年采用双引擎策略是合理的。从零开发一个生产级打包工具需要数年时间,而esbuild发展迅速,Rollup则已拥有完善的插件生态系统,将两者结合是一种务实的选择。但这也带来了长期风险:两个工具对相同源代码的处理方式可能不同,尤其是在CommonJS与现代ESM之间的交互方面——这是require()模块与现代ESM之间那种尴尬的桥梁。

Rolldown则试图用一个引擎解决所有这些问题。它基于Rust实现,拥有类似Rollup的插件API(大多数插件仍可正常使用),并于2026年5月7日正式发布1.0稳定版,其API设计固定,专为生产环境使用而打造。Vite 8本身也在2026年3月12日稳定下来,并默认启用Rolldown,无需用户额外选择。原本由esbuild处理的代码转换和压缩任务现在交由Oxc来完成,Oxc也是来自VoidZero的另一个Rust工具链(与Rolldown出自同一团队)。

标题:生产环境构建的速度可比传统 Rollup 快10到30倍。开发模式则表现更为出色。“完整包模式”会像生产环境一样对应用进行打包,而非直接提供原始的按文件分发的 ESM 格式。初步测试显示,冷启动速度可提升约3倍,完整重新加载速度快约40%,网络请求次数则减少大约10倍。对于那些代码量庞大的项目来说,开发阶段的未打包 ESM 已经无法满足需求,而这一新方案正好弥补了这一缺陷。

其结构上的优势更为简单:两种模式共用同一个引擎。由于不再存在不同的打包工具,那种“开发环境交互方式与生产环境不同”的问题也就不复存在了。

究竟出了什么问题

迁移并非毫无成本,对这一问题避而不谈无助于那些计划升级的人做出决策。

更严格的 CommonJS 互操作机制导致了包的故障。 模棱两可的 CJS 导出处理方式与旧版的 esbuild+Rollup 不同。在没有 module.exports.__esModule 且没有 default 属性的情况下,Rolldown 可能会将导入绑定到整个 module.exports 对象上,而非像那种宽松的构建栈那样尝试推测默认值:

// This used to just work under Vite 7 (esbuild + Rollup)
import DOMPurify from 'dompurify';
DOMPurify.sanitize(input);
// Under Rolldown's stricter CJS interop, this can throw:
// TypeError: e is not a function
// because the import resolved to the whole exports object,
// not the function you expected

这类代码存在危险属性:持续集成通常会忽略它。jsdom 或模拟测试套件很少会执行真正的生产环境构建结果。只有当浏览器加载生成的输出时才会出现故障。在排查依赖问题期间,可以设置 Vite 的 legacy.inconsistentCjsInterop: true 来恢复旧的宽松处理方式。

manualChunks 已被 advancedChunks 取代。这种替换并非简单的查找替换操作。在重新分组后,有些团队遇到了因分块顺序问题而引发的 ReferenceError: Cannot access 'x' before initialization 错误,还有报告指出在手动调整之前,默认的 Rolldown 分块方式会生成 575 个分块。

// Old, now-deprecated approach
build: {
  rollupOptions: {
    output: {
      manualChunks: {
        vendor: ['react', 'react-dom'],
      },
    },
  },
}
// Rolldown's replacement - more powerful, but a real migration
build: {
  rolldownOptions: {
    output: {
      advancedChunks: {
        groups: [
          { name: 'vendor', test: /node_modules/, priority: 100 },
        ],
      },
    },
  },
}

有记录的案例是:Cloudflare 的 @cloudflare/style-provider(混合 ESM+CJS 格式)出现了 createRenderer is not a function 错误,原因是 Rolldown 为 CJS 部分生成了匿名且无法访问的初始化函数。修复方案是将该包在 Vite 配置中关联到其 CJS 版本——通过 Rolldown 的互操作实现的纯 CJS 模式没有问题,但混合格式则存在问题。

应用代码外部问题:Rolldown的原生Rust绑定在StackBlitz WebContainers环境中无法加载,导致许多浏览器调试模板无法使用,直到相关项目固定使用Vite 7版本,同时上游团队也在追踪该问题。

更安全的迁移检查清单

已完成迁移的团队会聚焦具体细节,而非盲目“升级后等待问题解决”。

那些“Vite 7可用而Vite 8失败”的神秘故障:请先尝试使用experimental: { enableNativePlugin: false }选项。现在原生Rust插件为默认设置,关闭它们能解决不少难以理解的故障。

在部署之前,请在实际浏览器中加载真实的生产版本包。除非执行构建后的文件,否则jsdom无法检测到CJS交互类。

应将manualChunks改为advancedChunks视为一个独立项目,并为其设置专门的测试流程。代码块顺序问题在特定路径被访问之前往往看不出异常。

在升级到 Vite 8 之前,可使用 rolldown-vite(Vite 7 + Rolldown 预览版)对代码库进行风险检测。

如果某个关键依赖尚未准备好支持 Rolldown,那么在该构建中继续使用 Vite 7 是一个合理的选择——总比在截止日期前强行寻找脆弱的解决方案要好。

哪些情况会遇到问题

对于标准的 ESM 依赖以及轻量级/默认的代码分块方式,升级过程通常很顺利,仅此一点就值得进行升级。而自定义的 manualChunks、混合型的 CJS/ESM 包,或是特殊的运行环境(如浏览器沙箱、WebContainers),则需要预留足够的迁移时间,并对生成的产品进行浏览器测试。这类问题在 CI 测试中可能显示正常,但实际上只会在真实用户的实际代码包中出现问题。

更深层的启示

每当两个原本相互掩盖缺陷的系统被合并为一个时,之前看不见的缝隙就会同时显现出来。但这并不意味着合并是错误的。开发环境与生产环境的均衡确实是一种实质性的架构升级,而且性能指标也依然保持良好。这意味着“我们消除了分歧”与“在过渡期间会出现大量可被发现的特定漏洞”其实是同一件事在不同时间点的表现。对“逐步降级”策略持怀疑态度是错误的;而对没有经过浏览器加载的生产环境包的绿色持续集成方案持怀疑态度则是正确的。

迁移任务单上应写什么

应将此次升级视为带有验收标准的工程变更,而非单纯的依赖项升级。

建议的验收标准:

  1. 在逐步降级过程中,生产环境构建能够完成,并使用你预期的那些公共资源。
  • 关键的用户流程会在真实浏览器中针对构建好的代码包进行测试(而不仅仅是单元测试)。
  • 已知的混合型 CJS 依赖项要么会被别名处理,要么会升级,要么会通过带有所有者及过期日期的 legacy.inconsistentCjsInterop 来处理。
  • 代码分块策略会经过明确审查:要么在统计完请求次数后采用 Rolldown 的默认设置,要么通过专门的测试将 manualChunks 更改为 advancedChunks。
  • 那些无法加载原生绑定功能的环境(例如某些 WebContainer 托管平台)都有相应的固定版本或解决方案文档。
  • 如果任何标准未通过,则应继续使用 Vite 7 或 rolldown-vite,直到这些标准得到满足。发布一个更快但会破坏生产环境的代码打包工具并不能算是性能上的提升。

    为何一致性错误会让人感觉像是针对个人

    开发者们信任本地服务器。当本地服务器与生产环境构建不再相互冲突时,那些原本隐藏在冲突中的错误就会集中显现出来。这让人感觉像是“级联效应”引出了那些一直存在于CJS歧义或代码块结构中的问题。给这种模式命名能够减少恐慌:你并非在追踪随机的功能退化,而是在揭示双引擎时代被掩盖的缺陷。

    保留性能指标,坚持单引擎设计。但不要将测试结果正常就视为构建产物能够正常运行的证明。