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 报告,建议先开分支跑一遍。