配了八年 Vite,每次开发正常打包炸了我都以为是代码问题——今天发现根子不在代码,在两套引擎的行为差异里

配了八年 Vite,每次开发正常打包炸了我都以为是代码问题——今天发现根子不在代码,在两套引擎的行为差异里。

这是 Vite 长期存在的一个结构性痛点,但很少有人把它说清楚。

从 Vite 1.0 到 7.0,开发服务器和打包链路走的是两套完全不同的引擎:esbuild 负责开发时的即时转译,Rollup 负责生产最终打包。两套引擎,两个解析器,两套行为模型。开发时完全正常,打包时突然报错了——因为 esbuild 和 Rollup 对循环依赖处理细节不一样,对模块互操作的边界情况判断不一样,对 code splitting 边界的处理也不一样。这种 bug 本地根本复现不出来,上线之后才知道。

根本原因不是代码,是架构。

Vite 8 今年 3 月用 Rolldown 把这件事彻底变了。Rolldown 是 Vite 团队用 Rust 从头写的打包器,同时接管了原来 esbuild 的开发转译和原来 Rollup 的生产打包——一条链路,一个解析器,一套行为模型。dev 和 prod 彻底变成同一套引擎的两种用法,而不是两套不同的工具。

Rolldown 内置的 Oxc 工具链把 JS/TS/JSX 解析、React Refresh、tree-shaking 全收进了同一条 Rust 链路。@vitejs/plugin-react 从 v6 开始不再依赖 Babel,安装体积从约 45MB 降到了约 8MB——因为 Oxc 本身就是 Rust 原生的解析器,不再需要 Babel 那套 JavaScript 生态。

更重要的是打包产物的变化。Rolldown 的 tree-shaking 和 dead code elimination 比 Rollup 更激进,因为它能在单次遍历里分析完整模块图。实测一个 5,600 模块的项目,打包体积比 Rollup 输出小约 12%,且不需要任何配置改动——默认就开着了。

迁移对大多数项目来说就是改版本号。Vite 8 内部做了兼容层,vite.config.js 里的 esbuild 选项和 rollupOptions 会自动翻译成 Rolldown 能认的配置。Vue 插件、Svelte 插件基本原封不动跑起来。主要踩坑点:直接摸 esbuild 内部 AST 格式的插件需要作者主动更新;manualChunks 只接受函数格式了,对象写法会报错;自定义 Babel 配置要找对应 Oxc 版本替代。

Rolldown 和 Oxc 都是 VoidZero 团队维护的开源项目,VoidZero 今年被 Cloudflare 收购但所有项目保持开源。Vite 周下载量现为 4,160 万次/周,这次迁移是 JavaScript 生态有史以来规模最大的打包链路切换之一。

下一步:npm install vite@latest @vitejs/plugin-vue@latest 跑一遍,把打包产物 diff 一下 chunk 结构。有条件的话对比一下新旧版本的产物体积。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 15 阅读