Vite 8 迁移笔记:Rolldown 和 Oxc 接管后要改的配置
Vite 8.0 于 2026-03-12 发布,当前版本为 8.3.x。这一版把 Rolldown 作为唯一的 Rust 打包器,用 Oxc 负责 JS 转译与压缩,替代原先的 esbuild 和 Rollup。官方给出的数据是构建快 10–30 倍,插件保持兼容。迁移文档:https://vite.dev/guide/migration ;发布公告:https://vite.dev/blog/announcing-vite8 。
迁移路径:先在 Vite 7 上换包
大部分项目直接升上去即可,兼容层会把现有的 esbuild 和 rollupOptions 配置自动转换成 Rolldown / Oxc 的等价形式。项目大的话建议分两步:先在 Vite 7 上把 vite 换成 rolldown-vite,把只跟 Rolldown 有关的问题单独隔离出来,然后再升 Vite 8。这样出问题时能判断是 bundler 的锅还是 Vite 版本升级的锅。
Dependency Optimizer 改用 Rolldown
optimizeDeps.esbuildOptions 仍然可用,会被自动转成 optimizeDeps.rolldownOptions,但已标记弃用,后续删除。映射关系:
minify→output.minifytreeShaking→treeshakedefine→transform.defineloader→moduleTypespreserveSymlinks→!resolve.symlinksresolveExtensions→resolve.extensionsmainFields→resolve.mainFieldsconditions→resolve.conditionNameskeepNames→output.keepNamesplatform→platformplugins→plugins(部分支持)
JS 转译交给 Oxc,esbuild 变成可选依赖
esbuild 选项同样保留自动转换,但已弃用,映射到 oxc:
jsxInject→oxc.jsxInject;include/exclude保留esbuild.jsx→oxc.jsx('preserve'→'preserve','automatic'→{ runtime: 'automatic' })jsxImportSource→oxc.jsx.importSource;jsxFactory→oxc.jsx.pragma;jsxFragment→oxc.jsx.pragmaFragjsxDev→oxc.jsx.development;jsxSideEffects→oxc.jsx.puredefine→oxc.definebanner/footer没有对应项,需要自己写插件用transformhook
esbuild.supported Oxc 不支持。另外 Oxc transformer 目前不支持原生 decorator 的 lowering(oxc-project/oxc#9170),需要 Babel 或 SWC 处理。
Vite 内部不再直接使用 esbuild,它变成了可选依赖。插件里调 transformWithEsbuild 的,必须自己把 esbuild 装成 devDependency;该 API 已弃用,应改用 transformWithOxc。
压缩:Oxc Minifier 与 Lightning CSS
JS 压缩由 Oxc Minifier 完成。build.minify: 'esbuild' 可以切回旧行为,前提是装上 esbuild。esbuild.minify* 对应 build.rolldownOptions.output.minify,esbuild.drop 对应 build.rolldownOptions.output.minify.compress.drop*。属性改写相关选项(mangleProps、reserveProps、mangleQuoted、mangleCache)Oxc 不支持(oxc-project/oxc#15375)。
CSS 默认用 Lightning CSS。build.cssMinify: 'esbuild' 可切回,同样要装 esbuild。Lightning CSS 的语法降级能力更好,代价是 CSS bundle 体积可能略有增加。
CommonJS 默认导入行为统一
默认导入 CJS 模块现在的规则是:如果 importer 是 .mjs / .mts,或最近的 package.json 是 type=module,或 module.exports.__esModule 不为 true,则默认导入取 module.exports;否则取 module.exports.default。这可能破坏已有代码,临时回退用 legacy.inconsistentCjsInterop: true。
被移除和弃用的项
build.rollupOptions.watch.chokidar移除,迁移到build.rolldownOptions.watch.watcher。build.rollupOptions.output.manualChunks对象形式移除,函数形式弃用,改用 Rolldown 的codeSplitting。- 不再通过内容嗅探决定模块解析:
browser和module字段同时存在时,始终按resolve.mainFields顺序走。依赖旧行为的用resolve.alias或patch-package。 - 外部化模块的
require调用保留为require,不再转成import。需要转换时用 Vite 重导出的esmExternalRequirePlugin。 import.meta.url在 UMD / IIFE 输出里不再被 polyfill,默认替换成undefined。想保留旧行为,用define配合build.rolldownOptions.output.intro。build.rollupOptions→build.rolldownOptions,worker.rollupOptions→worker.rolldownOptions;build.commonjsOptions变成 no-op,build.dynamicImportVarsOptions.warnOnError也是 no-op;resolve.alias[].customResolver改用带enforce: 'pre'的resolveIdhook。- 给
import.meta.hot.accept传 URL 不再支持,改传 id(#21382)。
插件作者要注意的两点
Rolldown 会根据解析后的 id 扩展名自动设置 module type。在 load / transform hook 里把内容转换成 JS 的,可能需要在返回值里加上 moduleType: 'js'。
另外,JS API 里 build() 现在抛的是 BundleError,不再是插件的原始错误。类型是 Error & { errors?: RolldownError[] },具体错误列表在 e.errors。
默认浏览器目标提高
build.target 和 'baseline-widely-available' 一起上调:Chrome 107 → 111、Edge 107 → 111、Firefox 104 → 114、Safari 16.0 → 16.4(Baseline Widely Available 截至 2026-01-01)。
配置示例
迁移前(Vite 7):
import { defineConfig } from 'vite'
export default defineConfig({
esbuild: {
jsxInject: `import React from 'react'`,
define: { __DEV__: 'false' },
},
optimizeDeps: {
esbuildOptions: {
define: { global: 'globalThis' },
mainFields: ['browser', 'module', 'main'],
},
},
build: {
target: 'baseline-widely-available',
cssMinify: 'esbuild',
rollupOptions: {
output: {
manualChunks: { vendor: ['react', 'react-dom'] },
},
},
},
})
迁移后(Vite 8):
import { defineConfig } from 'vite'
export default defineConfig({
oxc: {
jsxInject: `import React from 'react'`,
define: { __DEV__: 'false' },
},
optimizeDeps: {
rolldownOptions: {
transform: { define: { global: 'globalThis' } },
resolve: { mainFields: ['browser', 'module', 'main'] },
},
},
build: {
target: 'baseline-widely-available',
rolldownOptions: {
output: {
// manualChunks 对象形式已移除,函数形式弃用,改用 codeSplitting
},
},
},
})
已知限制
Extglobs 暂不支持;TypeScript legacy namespace 仅部分支持;define 里的对象不共享引用;bundle 对象行为有变化(不支持给 bundle[foo] 赋值、引用不跨 hook 共享、structuredClone(bundle) 会报错,改用 structuredClone({...bundle}));Rollup 里并行的 hook 在 Rolldown 中顺序执行;某些情况下不再注入 "use strict";plugin-legacy 转 ES5 及以下不支持;给 build.target 传同一浏览器的多个版本现在会报错。
缺失的 API 包括 output.format 的 'system' 和 'amd',以及 shouldTransformCachedModule、resolveImportMeta、renderDynamicImport、resolveFileUrl 这几个 hook。parseAst / parseAstAsync 弃用,改用 parseSync / parse。注释的移除时机也提前了,现在在 renderChunk 之前而不是之后。