代码 Vite 8 迁移笔记:Rolldown 和 Oxc 接管后要改的配置

2026-10-28 21:04:52

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.minify
  • treeShaking → treeshake
  • define → transform.define
  • loader → moduleTypes
  • preserveSymlinks → !resolve.symlinks
  • resolveExtensions → resolve.extensions
  • mainFields → resolve.mainFields
  • conditions → resolve.conditionNames
  • keepNames → output.keepNames
  • platform → platform
  • plugins → 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.pragmaFrag
  • jsxDev → oxc.jsx.development;jsxSideEffects → oxc.jsx.pure
  • define → oxc.define
  • banner / footer 没有对应项,需要自己写插件用 transform hook

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' 的 resolveId hook。
  • 给 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 之前而不是之后。

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

推荐文章

程序员茄子在线接单