news 2026/9/11 11:57:14

Vite 8换芯实测:Rolldown取代esbuild+Rollup,构建提速3.19倍

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vite 8换芯实测:Rolldown取代esbuild+Rollup,构建提速3.19倍

上个月我把团队里一个压了很久的 monorepo 项目从 Vite 7 升到了 Vite 8。坦白讲,刚看到 release note 里“Rolldown 已正式取代 esbuild + Rollup 双引擎”这句话时,我下意识是嘀咕的——毕竟双引擎架构已经跑了好几年,大家早就习惯了 dev 用 esbuild、build 用 Rollup 的分工。但升级完在真实项目上连续跑了三轮构建,生产构建耗时从原来的 42.6 秒直接压到 13.35 秒,整整快了 3.19 倍。这个数字让我意识到,这次“换芯”不是挤牙膏式的优化,而是把 Vite 的构建骨架整个换掉了。

这篇文章我不会从“Vite 是什么”讲起,直接说 Vite 8 这次换芯换的到底是什么、Rolldown 为什么能快这么多、换完之后对现有插件和配置有什么影响,以及我在一个 260 多个路由、800 多个依赖的真实后台项目上跑出来的数据。如果你正打算升级,或者还在纠结要不要升,这篇完全可以当成一份踩坑笔记参考。

1. 双引擎时代:Vite 为什么曾经“一拆二”

1.1 开发模式和生产模式的分工

Vite 能火起来,核心是它把“开发体验”和“生产构建”两条链路分开设计。开发服务器用原生 ESM,浏览器按需加载模块,启动时只做依赖预构建,把 node_modules 里的 CommonJS 依赖提前转成 ESM,再用 esbuild 的转译速度处理 TS、JSX 这类需要编译的源码文件。这样做的直接好处是项目再大,冷启动也能控制在秒级,因为不会在启动时真的去打包全部源码,只需要编 node_modules 里被引用的那一批包。

生产构建就不一样了。要输出最终上线的文件,必须做全量依赖图分析、tree-shaking、代码分割、chunk 合并、资源指纹和压缩。Vite 这一层的选择是 Rollup。Rollup 是 JavaScript 生态里打包器的老牌选手,插件生态极其丰富,产物规则可控,能生成非常干净、可预测的 ESM 产物。但它的硬伤也很明显:纯 JavaScript 实现,处理大项目依赖图时,所有遍历都是单线程的 JS 对象操作,性能天然处于劣势。

于是 Vite 形成了大家熟悉的“双引擎”格局:esbuild 管开发阶段和依赖预构建,Rollup 管生产打包,生产阶段再调 esbuild 来压缩 JS。这个组合在当地时间是平衡速度与生态的最优解,至今很多 Build 工具教程里还会让你装 esbuild 和 rollup 两套依赖。

1.2 双引擎的心智负担与行为不一致

双引擎最大的问题就是“分裂”。同一段代码,在 dev 模式下由 esbuild 编译,在生产模式下由 Rollup 加一堆插件编译,结果很可能不一样。典型症状包括:ESM 和 CJS 互操作的细节差异、动态 import 的解析结果不同、CSS 注入顺序改变,甚至插件在 transform 阶段拿到的 sourcemap 格式都不同。开发时一切正常,一打包体积突然暴涨,或者某个依赖没被正确 tree-shake,这类问题排查起来极其痛苦。

插件体系也因此变得很拧巴。Vite 插件名义上兼容 Rollup 插件接口,但同一个 hook 在 dev 和 build 两个阶段执行路径并不完全一致,很多冷门插件只会在 build 下被触发。社区里不少插件作者抱怨过,自己写一个 Vite 插件等于同时维护两套行为,还得定期在两个引擎上做回归测试。

这就是为什么 Rolldown 的出现对整个前端工具链是一次“掀桌子”级别的变化——不是再优化 esbuild 和 Rollup 的配合,而是索性用一个新的引擎把两个都替掉。

2. Rolldown 是什么:Rust 重写打包器的底牌

2.1 从 rolldown-vite 实验包到 Vite 8 正式合入

Rolldown 是 VoidZero 团队主导的项目,目标是用 Rust 重写一个 Rollup 兼容的打包器。Vite 6 时代它就以rolldown-vite实验包的形式出现过,当时需要在 npm 里单独安装才能体验,很多人只是跑个 demo 就感受到差异了。到 Vite 8,Rolldown 终于被正式合入主线,esbuild 和 Rollup 在 Vite 内部的“双引擎”宣告退役。

这里有个关键点必须解释清楚:Rolldown 要做的是“替换”,不是“推倒重写”。因为 Vite 的插件 API 几乎就是 Rollup 的插件 API,只要 Rolldown 在 API 层面兼容 Rollup,Vite 生态里成千上万的插件就能平移过来,用户侧的迁移成本才能降到最低。现在你在 Vite 8 里配置build.rollupOptions依然有效,就是这个策略落地的结果。

2.2 Rust 到底快在哪些环节

打包过程里最吃性能的几个环节:源码解析、依赖解析、模块图构建、tree-shaking、代码生成、压缩。Rollup 用 JavaScript 在单线程里做,每个模块经过插件 hook 时都会产生大量函数调用、对象分配和垃圾回收。Rolldown 把这些流程几乎全部换成了 Rust 实现,并且用多线程并行处理没有依赖关系的模块。

光换语言不够,它还复用了 Oxc 生态。Oxc 是 Rust 写的 JS/TS 工具集合,包含 parser、transformer、resolver、minifier 等组件,这些组件直接内嵌到 Rolldown 里,省去了像 esbuild 那样作为独立服务进程的通信开销。我习惯用一个比喻:Rollup 像人工流水线,每个工位都要停下记录、检查、交接;Rolldown 是自动化并行流水线,工件以更高效率通过,而且多个工件同时处理。这也是为什么项目越大、依赖越多,提升越明显。

2.3 插件兼容并不是“零成本”

Rolldown 保留了绝大多数 Rollup 和 Vite 插件 hook,纯转换类插件基本都能直接跑。但有两种情况要特别小心:一是依赖 Rollup 内部对象或非公开 API 的插件,二是深度依赖renderChunkaugmentChunkHash这类输出阶段 hook 的插件。Rolldown 的执行上下文和传参对象结构跟 Rollup 存在差异,这些插件可能要等作者跟进适配。

在实际项目中,如果你用的是@vitejs/plugin-react@vitejs/plugin-vueunplugin-auto-importunplugin-vue-components这类主流插件,升级后基本无感。但如果项目里躺着一两个几年前写的、只在公司内部用的私有插件,那升级前就要把这些插件的适配情况列个清单。

3. 实测记录:真实项目从 Vite 7 升到 Vite 8

3.1 测试项目与硬件说明

先说测试对象。这是一个企业后台 monorepo,用 pnpm workspace 管理,包含admin-webshared-componentsapi-sdk三个包。技术栈是 React 18 + TypeScript 5.6 + antd 5 + less,页面路由 260 个左右,依赖总数量 850 个。项目中用vite-plugin-svg-icons做 svg 图标自动注册,这部分对构建阶段的资源处理有额外开销。

硬件环境是 MacBook Pro 14 英寸,M3 Pro 芯片,32GB 内存,Node 22.14 LTS。我特意把电脑重启后关掉多余进程再测,每个环节跑三遍取中位数,尽量排除系统状态带来的误差。

3.2 三个关键环节的耗时对比

指标Vite 7(esbuild + Rollup)Vite 8(Rolldown)提升倍数
冷启动 dev server(含依赖预构建)6.8s2.4s约 2.8 倍
依赖预构建单独耗时4.2s1.1s约 3.8 倍
首次热更新(触发组件失效后重建)2.1s0.8s约 2.6 倍
生产构建总耗时42.6s13.35s约 3.19 倍
构建产物 gzip 总体积4.18MB4.20MB基本持平

3.3 3.19 倍是怎么算出来的

标题里的 3.19 倍,指的是生产构建耗时。Vite 7 下完整打包是 42.6 秒,Vite 8 下是 13.35 秒,两者一除就是约 3.19。生产构建提升最猛,不难理解——这是全量重负载场景,要遍历每个模块、执行完整的插件流水线、生成 chunk,这些恰恰是 JavaScript 单线程最吃力的地方。Rolldown 全程走 Rust,瓶颈直接被拿掉了。

需要提醒的是,这个倍数会随项目规模变化。小型 demo 项目提升可能只有 1.5 到 2 倍,因为总耗时基数太小,很多固定开销摊不掉;超大项目比如 1000 个路由以上的中后台,我看到社区里有人测出 4 倍以上的提升。大家看评测数据时,最好结合自己的项目规模来判断。

4. 迁移到 Vite 8:配置与代码改动清单

4.1 真正不用改的部分

多数项目升级其实只做两件事:换依赖,重启。以我们的项目为例,先执行:

pnpm up vite @vitejs/plugin-react @vitejs/plugin-react-swc pnpm install

然后把 Node 版本确认到 Vite 8 要求的最低线以上。旧配置里build.rollupOptions只要不是用了特别冷门的 Rollup 内部 API,基本可以原样保留。像manualChunksexternaloutput.chunkFileNames这些常用配置,Rolldown 都做了兼容。我们迁移时最省心的是unplugin-auto-importunplugin-vue-components(如果用的是 Vue 项目)这类插件,它们在新引擎下表现稳定,没有出现自动化注册失效的情况。

4.2 需要重点检查的四个地方

第一处是minify配置。Vite 旧版本默认用 esbuild 压缩 JS,很多老项目会显式写成minify: 'terser'追求更高压缩率。到 Vite 8,默认压缩引擎换成了 Rust 生态里的 oxc minifier,速度和压缩率都更平衡。如果你之前显式指定了 terser,就要重新评估产物差异。terser 能做到的理论压缩率通常还是最高的,但耗时会明显增加;esbuild 快但产物略大;oxc 压缩率接近 terser 且速度极快,是大多数场景下的合理默认值。

第二处是依赖预构建相关配置。以前的optimizeDeps.esbuildOptions是为 esbuild 预构建准备的,换引擎后这一类配置基本失效,该清理就清理。项目里如果有optimizeDeps.force这类为了修复缓存问题而加的配置,建议先删掉跑一遍看是否还需要。

第三处是 CSS 处理。Vite 8 里 CSS 压缩可以走cssMinify: 'lightningcss',这是一条新路。如果你用了 PostCSS 插件,比如autoprefixer,我建议保留 PostCSS 链路,把cssMinify设成lightningcss时要注意它和个别 PostCSS 插件会不会重复处理一些属性前缀。

第四处是manualChunks的写法。Rolldown 对模块 ID 字符串的处理更严格,有些旧的正则匹配可能需要微调。我们项目里有一个基于路径拆分 vendor 的逻辑,升级后 vendor 命名多了一层目录前缀,花了几分钟改正则才恢复正常。

4.3 一个可直接参考的 Vite 8 配置示例

import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import { fileURLToPath } from 'node:url' export default defineConfig({ plugins: [react()], build: { minify: 'oxc', cssMinify: 'lightningcss', rollupOptions: { output: { manualChunks(id) { if (id.includes('node_modules')) { if (id.includes('react') || id.includes('scheduler')) { return 'react-vendor' } if (id.includes('antd') || id.includes('@ant-design')) { return 'antd-vendor' } return 'vendor' } } } } }, // rolldownOptions 在 Vite 8 下开放了部分引擎级配置, // 具体字段以你当前小版本的类型声明为准 rolldownOptions: { output: {} } })

注意:如果你的 CI 里长期缓存在旧版本 Vite 下生成的.vite缓存目录,升级后第一次构建最好rm -rf node_modules/.vite清一次缓存,避免 Rolldown 读取到旧引擎留下的中间产物。

5. 常见问题排查与避坑实录

5.1 插件在 Rolldown 下悄悄失效

我们内部有一个 i18n 文案提取插件,钩住 transform hook 收集中文文案。Vite 7 里跑得好好的,升到 Vite 8 后文案死活收集不全。排查时先开启了调试日志,命令是:

DEBUG=rolldown* pnpm build

看到日志后才发现,这个插件依赖的模块在 Rolldown 的依赖图里被判定为“未被实际引用”,在 transform 阶段之前就被裁剪了。解决方式是把信息收集逻辑从前置的 transform 挪到buildStartmoduleParsed钩子里,才能拿到完整的模块列表。这类问题最隐蔽,因为它不会报错,只是数据少了。

5.2 打包产物 chunk 数量和体积变化

Rolldown 的 chunk 合并策略跟 Rollup 不完全一样,默认的minChunkSize和合并粒度有差异。同一个项目,Rollup 打出来 47 个 chunk,Rolldown 打出来 39 个,体积基本持平。如果你的项目依赖强缓存策略,并且文件名里不带 hash,建议升级后在 CI 里重新固定一次基线。如果不需要固定文件名,那 hash 变化反而是正常的。

5.3 内存峰值上升与 CI 内存不足

多线程并行带来的副作用是内存峰值升高。我们本地 32GB 内存几乎无感,但 CI 的 8GB 容器在构建时出现了两次 OOM。这种情况优先考虑降低并发,Vite 8 的rolldownOptions暴露了与并发 worker 相关的实验性字段,不同小版本字段位置可能不一样,直接查你当前安装版本的类型定义最准确。其次是给 Node 进程加大内存限制,或者把 CI 构建机的内存规格往上提一档。

5.4 CSS 样式覆盖顺序变化

我们项目里有用 less 写主题变量的场景,升级后出现了一个全局样式的覆盖顺序被改变的问题。原因是 CSS 注入阶段对模块遍历顺序的处理变了,部分@import和组件内样式之间的先后关系跟 Rollup 时代不同。排查方法是在首屏页面对比 Vite 7 和 Vite 8 生成的 style 标签顺序,找到差异后用css.preprocessorOptions里的 additionalData 统一注入公共变量,把顺序依赖降到最低。

5.5 遇到疑似 Bug 怎么高效反馈

Rolldown 还在快速迭代阶段,遇到问题别急着降级。先在 GitHub 搜 issue,如果没找到,提 issue 时最少要带三样东西:项目的vite.config.tsDEBUG=rolldown*的构建日志、一个可复现的最小仓库。只贴一段报错信息的话,维护者很难定位,最后大概率又是白等一趟。

6. 写在最后的一些体会

这次升级让我最感慨的其实不是快 3 倍这个数字,而是整个前端工具链的整合趋势。Vite 早期靠 esbuild 解决“快”,靠 Rollup 解决“全”,本质上是在两个引擎之间反复横跳。Rolldown 把这两件事统一到一个引擎里,从开发到构建、从转译到压缩,行为和结果完全一致,这种一致性带来的维护成本下降,比单纯的构建提速更值钱。

如果你现在问我“要不要升”,我的建议是:主流技术栈的常规项目,升。你的收益非常直接,构建快、配置简化、排查路径单一。但如果项目里压着大量私有插件,或者长期依赖某些冷门的 Rollup 行为,那就先拉一个分支跑一遍pnpm build,把插件兼容清单过掉再合并。以我现在对这个生态的判断,一年后再看,Rolldown 只会更成熟,而这个升级窗口会越来越平滑。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 11:57:12

awesome-design-md:直接拿走 73 份 DESIGN.md,3 步生成品牌同款 UI

awesome-design-md:直接拿走 73 份 DESIGN.md,3 步生成品牌同款 UI 【免费下载链接】awesome-design-md A collection of DESIGN.md files analysis by popular brand design systems. Drop one into your project and let coding agents generate a mat…

作者头像 李华
网站建设 2026/9/11 11:57:06

TCP协议深度解析:从设计哲学到tcpdump抓包实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 11:57:03

AutoHedge:面向不可靠API的分布式韧性契约范式

1. AutoHedge不是自动对冲,而是分布式任务协同的底层范式重构 AutoHedge这个词,第一次在MIT实验室的内部技术简报里出现时,我正盯着一段用Python写的Docker Swarm服务巡检脚本发呆。当时没人把它当真——毕竟“Hedge”在金融语境里是“对冲”…

作者头像 李华
网站建设 2026/9/11 11:56:19

四激光雷达+华为ADS 5:岚图泰山X8智能驾驶深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 11:55:27

Golang处理EXIF:提取拍摄时间与GPS坐标及修改实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华