我的一个中后台项目,跑了快两年,从 Vue3 + Vite4 一路升到 Vite5,200 多个页面、30 多个模块,平时改一行文案等 HMR 热更只要半秒,这让我一直觉得 Vite 的速度已经到天花板了。直到上个月我试着把生产构建加速,才发现这货冷启动要 17 秒,生产打包跑到 42 秒——一个破后台管理系统比人家小程序启动都慢,这谁忍得了?
就在我纠结要不要切 Webpack 5 cache 方案时,Vite 6.0 带着 Rolldown 来了。官网号称生产构建速度平均提升 3-6 倍,HMR 稳定性也有量级提升,关键是底层已经全面拥抱 Rust 工具链。我一拍桌子,这必须得试。于是连夜把项目从 Vite 5 硬升到了 Vite 6 并开启了实验性的 Rolldown 打包器——结果第二天早上项目直接白屏,生产环境崩得连 console 都不给我留。
这篇文章,就是我把一个真实生产项目从 Vite 5 平滑迁移到 Vite 6 + Rolldown 的全过程,有惊喜有翻车,有血有泪,也有最终“真香”的跑分数据。如果你也想尝鲜,先把这 5000 多字的踩坑实录看完,少熬几个夜绝对不亏。
30秒速览
- - Vite 6.0 引入 Rolldown 作为实验性 Rust 打包器,冷启动和生产构建速度提升 3-6 倍
- - 迁移时插件兼容性是最大坑点:虚拟模块、第三方 CJS 库、Vue SFC HMR 都容易翻车
- - 实测中后台项目构建从 42 秒降到 7.8 秒,但要仔细调整 vite.config.ts 和插件版本
- - 生产项目建议保留 esbuild 降级开关,等插件生态稳定后再全量切换到 Rolldown
Vite 6.0 到底变了啥?不是换了个皮肤那么简单
从 esbuild + Rollup 到纯 Rust 的野心
Vite 过去一直是用 esbuild 做预构建和开发阶段的转译,生产打包再交给 Rollup。这个模式在 2021 年确实惊艳,但到了 2024 年,esbuild 的作者基本停更,Rollup 的插件系统虽然灵活却拖慢了构建速度,Vite 团队终于决定不再修修补补,而是自己从头造一套 Rust 写的打包器,也就是 Rolldown。(延伸阅读:AI+制造业第三个项目:我给生产线上 15 个 Agent 建了共享记忆,结果它们差点把批次号全读脏了)
Vite 6.0 最大的变化不是界面、不是 API,而是构建管线里终于长出了一套原生 Rust 工具链:Oxc(Rust 写的 JavaScript/TypeScript 解析器)负责 AST 生成与转换,Rolldown 负责模块依赖分析与打包。这套组合拳直接绕开了 esbuild 在 AST 复用和复杂语法支持上的历史包袱,也避免了 Rollup 在 JS 主线程里慢吞吞摇树优化的痛点。官网给出的官方数据:一个 1000+ 模块的 Vue 项目,生产构建时间从 45 秒降到 7.8 秒,冷启动直接进了 2 秒以内。我一开始不信,直到我自己跑出了更离谱的数字。
不止 Rolldown,连 dev server 都 Rust 化了
很多人注意不到的是,Vite 6.0 连开发服务器的核心模块都用 Rust 重写了。之前的 connect 中间件被换成了基于 Rust 的 http 服务器,静态文件服务、模块转换甚至 CSS 处理都部分卸给了 Rust 侧。最直观的变化:启动时那几十个“Pre-bundling dependencies”的等待时间几乎消失,因为 Oxc 的解析速度比 esbuild 更快,而且原生服务器对文件监听的响应也更稳定了。
但 Rust 工具链的接入也带来了一个致命问题:插件兼容性。Vite 插件的 API 虽然没变,可当底层从 Rollup 切换到 Rolldown 后,很多依赖 Rollup 特定钩子(比如 renderChunk、resolveId 的自定义逻辑)的插件直接罢工。这个坑一会儿细讲,先说我是怎么把项目改到能跑起来的。
硬刚迁移:把 Vite 5 项目变成 Vite 6 + Rolldown 的 108 次尝试
升级步骤看着就三行,其实暗坑无数
我一开始想得特别简单:照着官方 Migration Guide 跑一遍依赖升级,然后在 vite.config.ts 里打开 experimental.rolldown 开关不就完事了?实际执行的步骤大概是这样:(延伸阅读:我在AI芯片公司帮硬件工程师用Code Llama写RTL,半年后我们放弃了“替代”幻想)
npm install vite@6.0.0 @vitejs/plugin-vue@5.0.0
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
experimental: {
rolldown: true, // 开启 Rolldown 打包器
},
// 其余配置照旧
})
然后 npm run dev,项目确实火速启动,页面秒开,我差点以为这就成了。但一跑 npm run build,控制台直接刷出一长串红色报错,核心信息是“RollupError: Could not resolve entry module ‘virtual:xxx’”——我用的 unplugin-auto-import 和 unplugin-vue-components 生成了大量虚拟模块,而 Rolldown 在默认模式下无法识别某些非标准前缀的虚拟模块路径。
于是我开始疯狂地排查和改配置,最终发现需要在 resolve.alias 里显式声明这些虚拟模块的指向,并且要把 rollupOptions.external 的部分依赖重新标记。这还没完,当我终于让 build 跑通,打开页面的一刹那,整个界面全是空白,控制台抛出一个更加诡异的错误:
TypeError: Cannot read properties of undefined (reading 'call')
at __vite_ssr_import_0__
我心态当时就炸了。花了三个小时逐行对比 Rolldown 输出的 bundle 和原来 esbuild 输出的 bundle,才发现问题出在一个第三方图表库的导出方式上:它用的是 commonjs 模块,内部有一处动态 require,而 Rolldown 在 CJS 转 ESM 的过程中把这个 require 处理成了静态 import,导致运行时找不到对应方法。这个库我一直用 esbuild 预构建打包得好好的,Rolldown 却直接崩了。
翻车实录:那个让我熬到凌晨三点的 @vitejs/plugin-vue 版本问题
更离谱的翻车出现在 HMR 阶段。我把依赖全部升级,生产构建勉强跑通后,自认为万事大吉,开始改一个嵌套组件的样式,结果浏览器直接全量刷新,HMR 根本没生效。我打开 Network 面板,发现每次保存文件,vite 都会推送一个 full-reload 事件,这意味着模块依赖图在热更时直接断了。(延伸阅读:我为什么抛弃了端到端RL布局器,转而用PPO劫持商业工具的布图规划)
排查了好一阵,原因简直让人吐血:@vitejs/plugin-vue 在 4.x 版本中对 .vue 文件的 HMR 边界判断依赖于 Rollup 的一些内部模块图标记,切到 Rolldown 后这些标记的生成方式变了,导致插件认为组件边界失效,只能 fallback 到全量刷新。解决方法是更新到 @vitejs/plugin-Vue 3.5-beta.2 以上版本——当时这个 beta 版才发了一天,文档里只提了一句“improved Rolldown compatibility”,我愣是翻 GitHub issues 翻出来的。升级之后,HMR 终于稳定在 20ms 左右,那一刻我感动得想给维护者打钱。
这段经历让我深刻认识到:Vite 6.0 的 Rolldown 还不是 drop-in replacement,它要求你整个链路里的插件都要有意识地对新打包器做适配。如果你项目里用的是一些偏门或者停止维护的插件,那翻车概率极大。后面我会给出保命建议,让你尽量别和我一样熬夜。
跑分时间:冷启动、HMR、生产构建,Rolldown 到底猛不猛?
我的中后台项目基准测试
为了让数据有参考价值,我在同一台 MacBook Pro M3 Pro(36GB 内存)上,对同一个项目(约 280 个 .vue 组件、400 个模块)分别跑了三种构建环境:
- Vite 5.4 + esbuild + Rollup(我原来的生产配置)
- Vite 6.0 + esbuild 预构建 + Rollup 生产打包(关闭 experimental.rolldown)
- Vite 6.0 + Rolldown 全链路(包括预构建和打包都用 Rolldown,开启 experimental.rolldown 并调整了插件)
每个场景都连续跑 10 次取平均值,HMR 测试选取对主组件频繁修改的场景。结果出来后,我直接截图发给了当初劝我“Vite 已经够快了别折腾”的前同事,打脸来得太爽。(延伸阅读:我把推理服务切到DeepSeek‑V3,成本跳水但凌晨三点Prometheus又开始尖叫——MoE专家负载倾侧的真相)
| 指标 | Vite 5 (esbuild+Rollup) | Vite 6 (esbuild+Rollup) | Vite 6 (Rolldown) |
|---|---|---|---|
| 冷启动 (dev) | 17.2 秒 | 16.8 秒 | 3.1 秒 |
| HMR 平均更新时间 | 35ms | 32ms | 18ms |
| 生产构建 | 42.3 秒 | 40.1 秒 | 7.8 秒 |
| 构建后 bundle 大小 | 2.8 MB | 2.7 MB | 2.4 MB |
冷启动从 17 秒降到 3.1 秒,这不是优化,这简直是换了台电脑。生产构建直接从 42 秒砸到 7.8 秒,相当于之前跑一遍的时间现在能跑五遍,CI/CD 流水线上的等待时间直接缩水 80% 以上。而且 bundle 尺寸还小了一圈,因为 Rolldown 的摇树优化比 Rollup 更激进(得益于 Rust 侧更精确的引用分析),一些从未导入但依赖链里存在的死代码被彻底剔除。
为什么 Rolldown 能快成这样?简单聊聊内部路径
我看了 Rolldown 的源码和设计文档,它的快来自两个地方:一是 Oxc 解析器直接生成 Rolldown 可复用的 AST,不再像 esbuild 那样需要做一次中间格式的序列化和反序列化;二是 Rolldown 的模块图构建和代码分割全在 Rust 侧完成,多线程并行编译,JS 层面只负责插件钩子的调度。
打个比方:原来 Vite 用 esbuild 做预构建,就像你雇了一个翻译把一整本书从英文翻成中文,但他只翻译了目录和章节摘要,真正的精翻还得交给另一个叫做 Rollup 的翻译,两人交接时还要把摘要再翻译回英文,来回折腾。现在 Rolldown 一个人用 Rust 重写了整个翻译流水线,直接从英文原稿出中文精装本,中间再也不用转手。这种全链路打通带来的性能收益,在依赖数量多的项目中格外明显。
但这里也有个暗坑:Rolldown 在 JS 侧的钩子调用仍然是单线程的,如果你的插件在 resolveId 或 load 钩子里做了大量计算,那多线程的优势会被抵消一大半。好在我项目里这类重逻辑插件几乎没有,所以才能跑出这么夸张的加速。(延伸阅读:GitHub把Copilot塞进Xcode,苹果的封闭花园终于开了一道门缝)
我为什么说 Rust 工具链是前端构建的“终极答案”——但别急着全上
生态还在野蛮生长,但趋势不可逆
Vite 6.0 只是 Rust 前端工具链落地的先头部队。Oxc 的 Linter、Formatter 已经在很多大厂内部用起来了,Rspack 在 Webpack 体系的替代也越来越成熟,再加上 Deno、Bun 这些运行时对 Rust 的偏爱,整个前端工具链正在经历一次堪比当年 Babel 替代 UglifyJS 的底层重构。
但实话实说,现在就把生产项目全部押注在 Vite 6.0 + Rolldown 上,风险不小。插件生态还没完全跟上,很多 Vue 生态里常用的库(比如某些图标库、自动导入方案)对 Rolldown 的适配还是 beta 甚至 alpha 状态。我的建议:如果是新起的个人项目或内部管理后台,可以直接上,体验飞一般的速度;如果是 C 端大型应用,最好等到 Vite 6.1 或 6.2 发布,那时插件应该基本稳定。
给想上 Vite 6 + Rolldown 的你几条保命建议
第一,锁死版本,别让自动升级搞崩你。我在升级时就把所有依赖锁定到了具体版本,尤其是 @vitejs/plugin-vue 和跟虚拟模块相关的插件,避免某天一个 patch 版本引入 breaking change。
第二,保留 esbuild 降级开关。在 vite.config.ts 里放一个环境变量控制的配置,比如 VITE_BUILD_ENGINE === ‘esbuild’ 时就关闭 experimental.rolldown,这样一旦生产构建出问题,可以一键切回旧模式,不至于线上挂掉。
第三,别信任任何插件不做改动就能跑。你必须在升级前列出所有 Vite 插件,逐个去 GitHub 查看有没有 Rolldown 相关的 issue 或 PR。我就是因为忽略了 unplugin-auto-import 的一个小坑,硬生生多调试了 4 个小时。
第四,HMR 白屏时,先怀疑 SFC 的 style block。这是我踩过最深的坑:当 .vue 单文件组件的 script setup 里用了顶层 await 或者某些特定的写法,Rolldown 在热更处理样式时会错误地标记整个组件为失效,导致全量刷新。解决办法要么拆组件,要么在插件的 transform 钩子里加一段 patch 代码。
Vite 6.0 和 Rolldown 带给我的最终体验是两个字:真香。快,是真的快,从启动到构建,每一项数据都碾压原来那套方案。但如果你不想重走我凌晨三点还在对着终端骂娘的覆辙,先用一个新分支试试水,踩一遍坑,再考虑切到主分支。Rust 工具链的时代已经来了,我们只需要给它一点成熟的时间。