Vite 8 升级笔记:Rolldown + Oxc 替换后真正会出问题的几处
Vite 8(2026-03-12)把打包器从 Rollup 换成了 Rolldown,把转换器从 esbuild 换成了 Oxc。插件接口层面基本兼容,但有几处语义发生了根本变化:CJS default 导入规则、对象形式 manualChunks、esbuild 变成可选依赖、UMD/IIFE 里的 import.meta.url、默认浏览器目标,以及 import.meta.hot.accept 签名。下面按升级时容易出问题的顺序记录。
- 迁移指南:https://vite.dev/guide/migration
- 发布公告:https://vite.dev/blog/announcing-vite8
分两步升级:先换 rolldown-vite,再升到 8
rolldown-vite 这个包就是用 Rolldown 实现的 Vite 7。先在现有 Vite 7 项目里把打包器换掉,跑通插件链、比对构建产物,再升到 8。项目大时官方也推荐两步走,避免一次同时改版本号和底层实现,出问题不好定位。
配置项改名
顶层配置中的 rollupOptions 统一改成 rolldownOptions,esbuild 换成 oxc。旧名暂时还能用,但已经标记弃用。
// vite.config.js
export default {
build: {
// 旧:rollupOptions
// 新:rolldownOptions
rolldownOptions: {
output: {
// 对象形式的 manualChunks 已被删除,见下文
manualChunks(id) {
if (id.includes('node_modules')) return 'vendor'
},
},
},
},
worker: {
// worker.rollupOptions -> worker.rolldownOptions
rolldownOptions: {},
},
// 旧:esbuild
// 新:oxc
oxc: {
jsxInject: `import React from 'react'`,
},
}
依赖预构建走 Rolldown,optimizeDeps.esbuildOptions 已弃用,会自动转换为 optimizeDeps.rolldownOptions:
// optimizeDeps.esbuildOptions -> optimizeDeps.rolldownOptions
{
minify: true, // -> rolldownOptions.output.minify
treeShaking: true, // -> treeshake
define: {}, // -> transform.define
loader: {}, // -> moduleTypes
preserveSymlinks, // -> !resolve.symlinks
resolveExtensions, // -> resolve.extensions
mainFields,
conditions, // -> conditionNames
keepNames,
platform,
plugins, // 部分支持
}
JS 转换的 esbuild 选项同样会自动映射到 oxc:
// esbuild -> oxc
{
jsxInject, // -> oxc.jsxInject
include, exclude, // 支持
jsx, // 'preserve' | 'automatic' -> oxc.jsx: { runtime: 'automatic' }
jsxImportSource, // -> oxc.jsx.importSource
jsxFactory, // -> oxc.jsx.pragma
jsxFragment, // -> oxc.jsx.pragmaFrag
jsxDev, // -> oxc.jsx.development
jsxSideEffects, // -> oxc.jsx.pure
define, // -> oxc.define
}
// esbuild.supported Oxc 不支持
另外,Oxc 转换器目前还不支持把原生装饰器降级,需要走 Babel 或 SWC。
CJS default 导入语义变严
这是最容易在运行时静默出错的一处。从 CJS 模块默认导入时,只有满足下面任一条件,default 才等于 module.exports:
- 导入方是
.mjs/.mts; - 最近的
package.json里type: "module"; module.exports.__esModule !== true。
否则 default 取 module.exports.default。以前 dev 和 build 两套行为不一致,现在统一成一套,因此有些以前能跑的代码会取到 undefined。想恢复旧行为,可以设 legacy.inconsistentCjsInterop: true。
对象形式的 manualChunks 被删除
output.manualChunks 的对象形式已经移除,函数形式也已弃用,改为使用 Rolldown 的 codeSplitting 选项。上面配置块里保留的是函数写法,但如果项目里靠对象映射分包,必须改写。
esbuild 变成可选依赖
Vite 自身不再直接依赖 esbuild,它只是可选的。之前依赖 transformWithEsbuild 的插件会直接报错找不到模块,需要在项目里把 esbuild 装回 devDependency;同时 transformWithEsbuild 已弃用,改用 transformWithOxc。
压缩同理:JS 压缩换了 Oxc minifier,build.minify: 'esbuild' 仍可回退,但前提是装了 esbuild。esbuild.minify* 系列选项迁到 build.rolldownOptions.output.minify,esbuild.drop 迁到 output.minify.compress.drop*。属性名混淆(mangleProps 等)Oxc 不支持。
CSS 压缩默认换成 Lightning CSS,可用 build.cssMinify: 'esbuild' 回退,产物体积可能会略微增加。
UMD / IIFE 里的 import.meta.url 变 undefined
import.meta.url 不再在 UMD 和 IIFE 产物中做 polyfill,默认被替换成 undefined。依赖这个值的库在非 ESM 构建下会出错,需要用 define 配合 build.rolldownOptions.output.intro 手动补回去。
默认浏览器目标抬高
build.target 的默认基线更新为 2026-01-01 的 Baseline Widely Available:Chrome 107 → 111,Edge 107 → 111,Firefox 104 → 114,Safari 16.0 → 16.4。老浏览器需要显式配 build.target。注意现在给 build.target 传同一个浏览器的多个版本会直接报错。
import.meta.hot.accept 不再接受 URL
import.meta.hot.accept 带 URL 参数的写法已移除(#21382),HMR 边界要改成传模块依赖本身。
其他会影响构建结果的改动
- 模块解析不再做 format sniffing:
browser和module字段同时存在时,以前 Vite 会读文件内容,给浏览器挑 ESM 版本,现在严格按resolve.mainFields的顺序。需要用resolve.alias或patch-package兜底。 - externalized 模块的 require 原样保留:不再自动转成
import。要转就用esmExternalRequirePlugin,它从vite里重新导出。 - watch 配置:
build.rollupOptions.watch.chokidar移除,换成build.rolldownOptions.watch.watcher。 - JS API 错误类型:
build()抛BundleError,不再抛原始错误,调用方需要改 catch 逻辑。 - 插件作者注意:模块类型自动检测的变化可能要求你在
load/transform的返回值里显式给出moduleType: 'js'。 - 转为 no-op 或移除的项:
build.commonjsOptions变 no-op,build.dynamicImportVarsOptions.warnOnError变 no-op,resolve.alias[].customResolver移除。
边界情况
extglob 暂不支持;TS 的 legacy namespace 只部分支持;define 对对象不共享引用;bundle 对象上不能给 bundle[foo] 赋值,hook 之间也不共享引用,structuredClone(bundle) 会抛 DataCloneError,需要写成 structuredClone({...bundle});原本并行的 hook 变成串行;"use strict" 有时不会被注入;plugin-legacy 的 ES5 目标不支持;'system' / 'amd' 输出格式不再支持;shouldTransformCachedModule、resolveImportMeta、renderDynamicImport、resolveFileUrl 这几个 hook 不支持;parseAst 弃用,改用 parseSync / parse。
官方公告给出的构建提速数字最高到 10–30 倍,插件兼容性按完全兼容处理。实际升级时,上面这些语义变化比性能数字更值得先过一遍。