代码 Vite 7 升到 Vite 8:这些改动不报错,只在运行时出问题

2026-11-13 21:04:36

Vite 7 升到 Vite 8:这些改动不报错,只在运行时出问题

Vite 8 用 Rolldown(Rust)替换 Rollup、用 Oxc 替换 esbuild,构建速度提升 10–30x,插件 API 保持与 Rollup 兼容。Node 要求 20.19+ / 22.12+,且只支持 ESM。

下面这些问题只写会失败的情况:这些地方升级时不会报错,但会在运行时出错。

  • 迁移指南:https://vite.dev/guide/migration
  • 发布公告:https://vite.dev/blog/announcing-vite8

1. CJS default import 的解析规则变了,而且不报错

Vite 8 统一了 CommonJS 互操作:import x from 'cjs-pkg' 里的 x 到底是 module.exports 还是 module.exports.default,取决于三个条件。满足下面任一条,default 就是整个 module.exports:

  • importer 是 .mjs / .mts
  • 最近的 package.json 里 type: "module"
  • 被引模块的 __esModule 不为 true

否则 default 取 module.exports.default。

以前 dev 和 build 的行为并不一致,所以这个差异可能一直存在,只是因为只在一边运行而没有暴露。升级后的表现是没有编译错误,运行时拿到 undefined。legacy.inconsistentCjsInterop: true 可以恢复旧行为,但这只是临时回退,不该长期保留。

2. build.rollupOptions 改名为 build.rolldownOptions

worker.rollupOptions 同理。旧字段有兼容层,不会中断构建,但每次构建都会打警告。配置里出现 rollupOptions 的地方一并改掉,别让警告长期留在输出里。

3. output.manualChunks 的对象形式被直接移除

对象形式没有兼容,只有函数形式还在,且已弃用。分包逻辑要迁到 codeSplitting。如果配置里是对象形式,这里不会像字段改名那样给出提示。

4. build.commonjsOptions 变成 no-op

不报错,也不生效。为某个 CJS 包专门写的 workaround(include / transformMixedEsModules 之类)会静默失效,表现是那个包在构建产物里行为异常,而不是构建失败。

5. 依赖优化器与 JS 转换

依赖优化器改用 Rolldown,optimizeDeps.esbuildOptions 自动转成 optimizeDeps.rolldownOptions,字段映射覆盖 minify、treeShaking、define、loader、moduleTypes、preserveSymlinks、resolveExtensions、mainFields、conditions、keepNames、platform、plugins,esbuildOptions 本身已弃用。

JS 转换改用 Oxc,esbuild 字段自动转 oxc,映射覆盖 jsxInject、include、exclude、jsx、jsxImportSource、jsxFactory、jsxFragment、jsxDev、jsxSideEffects、define。没有对应实现的是 esbuild.supported(oxc#15373);另外 Oxc transformer 目前不支持降级原生 decorators(oxc#9170),这类项目需要走 Babel 或 SWC。

esbuild 也从依赖里变成可选。插件里用了 transformWithEsbuild 的,要自己安装 esbuild;该函数已弃用,改用 transformWithOxc。

JS 压缩换成 Oxc Minifier,build.minify: 'esbuild' 可以回退,同样需要自己安装 esbuild。mangleProps、reserveProps、mangleQuoted、mangleCache 不被 Oxc 支持(oxc#15375)。CSS 压缩默认走 Lightning CSS,bundle 体积可能略有增长。

6. 默认浏览器目标上调

对齐 Baseline Widely Available(2026-01-01):Chrome 107→111、Edge 107→111、Firefox 104→114、Safari 16.0→16.4。构建过程不会有任何提示,只有用户真的用老浏览器打开时才炸。

7. 插件侧的变化

  • moduleParsed 在 dev 下不再调用。
  • esbuild 原生的 onLoad / onResolve 插件不被支持。
  • transform 钩子返回非 JS 内容时,必须带 moduleType: 'js'。
  • 不支持的 Rollup 钩子:shouldTransformCachedModule、resolveImportMeta、renderDynamicImport、resolveFileUrl。
  • parseAst / parseAstAsync 弃用,改 parseSync / parse。
  • 注释在 renderChunk 之前就被移除,依赖注释做处理的插件要注意。

8. 其他零散改动

  • build() 抛出 BundleError(Error & { errors?: RolldownError[] }),错误处理分支需要跟着调整。
  • 不再用 format sniffing 决定 browser / module 字段,始终按 resolve.mainFields 顺序解析。
  • external 模块的 require 调用保留为 require,不再转成 import;需要转换时用 esmExternalRequirePlugin。
  • UMD / IIFE 输出不再 polyfill import.meta.url,默认替换为 undefined。
  • build.rollupOptions.watch.chokidar 移除,改 build.rolldownOptions.watch.watcher。
  • build.dynamicImportVarsOptions.warnOnError 变 no-op,resolve.alias[].customResolver 移除。

迁移路径

不要直接从 Vite 7 跳到 Vite 8。先换成 rolldown-vite@7(Vite 7 + Rolldown)作为中间步骤,把打包器行为差异和上面这些静默改动暴露在影响面更小的版本上,再升 8。

用 Yarn PnP(nodeLinker: pnp)的项目要单独验证:rolldown-vite 的 issue 里已有多份 Failed to resolve import 报告,建议先开分支跑一遍。

复制全文 生成海报 Vite Vue 前端构建 迁移 MTS

推荐文章

程序员茄子在线接单