跳到主要内容

Vite 8 迁移指南

如果你正在从 Vite 7 升级到 Vite 8,本指南将帮助你了解主要变更和迁移步骤。Vite 8 是一个重要版本,引入了 Rolldown 作为统一打包器,这带来了一些破坏性变更。

升级前准备

在开始迁移之前,建议先完成以下准备工作:

  1. 确保你的项目使用 Vite 7 的最新版本
  2. 查看 Vite 7 的弃用警告,提前处理这些问题
  3. 在单独的分支上进行迁移测试
  4. 准备好回滚方案

Node.js 版本要求

Vite 8 要求 Node.js 版本 20.19+22.12+。如果你的项目使用更低版本的 Node.js,需要先升级。

# 检查当前 Node.js 版本
node --version

# 使用 nvm 升级到 LTS 版本
nvm install --lts
nvm use --lts

浏览器目标变更

Vite 8 默认的浏览器目标已更新为 Baseline Widely Available(2026-01-01 时已发布约 2.5 年的浏览器):

浏览器Vite 7Vite 8
Chrome107111
Edge107111
Firefox104114
Safari16.016.4

如果你的应用需要支持更旧的浏览器,可以在配置中指定:

export default defineConfig({
build: {
target: 'chrome80',
},
})

或使用 @vitejs/plugin-legacy 插件。

Rolldown 统一打包器

Vite 8 最大的变化是使用 Rolldown 替代了 esbuild 和 Rollup,成为统一的打包器。这意味着:

  • 开发环境的依赖预构建使用 Rolldown
  • JavaScript 转换使用 Oxc
  • 生产构建使用 Rolldown
  • JavaScript 压缩使用 Oxc Minifier
  • CSS 压缩使用 Lightning CSS

渐进式迁移策略

如果你担心一次性迁移风险太大,可以采用渐进式迁移:

第一步:在 Vite 7 中测试 Rolldown

{
"devDependencies": {
"vite": "npm:[email protected]"
}
}

rolldown-vite 是 Vite 7 的 Rolldown 集成版本,可以让你提前体验 Rolldown 的行为。

第二步:确认无问题后升级到 Vite 8

{
"devDependencies": {
"vite": "^8.0.0"
}
}

依赖优化配置迁移

Rolldown 现在用于依赖优化,替代了之前的 esbuild。

旧配置(已废弃)

export default defineConfig({
optimizeDeps: {
esbuildOptions: {
target: 'es2020',
},
},
})

新配置

export default defineConfig({
optimizeDeps: {
rolldownOptions: {
target: 'es2020',
},
},
})

选项映射表

esbuildOptionsrolldownOptions
minifyoutput.minify
treeShakingtreeshake
definetransform.define
loadermoduleTypes
preserveSymlinks!resolve.symlinks
resolveExtensionsresolve.extensions
mainFieldsresolve.mainFields
conditionsresolve.conditionNames
keepNamesoutput.keepNames
platformplatform
pluginsplugins(部分支持)

Vite 仍会自动转换 esbuildOptionsrolldownOptions,但建议尽早迁移。

JavaScript 转换配置迁移

Oxc 现在用于 JavaScript 转换,替代了 esbuild。

旧配置(已废弃)

export default defineConfig({
esbuild: {
jsxInject: `import React from 'react'`,
jsxFactory: 'h',
jsxFragment: 'Fragment',
},
})

新配置

export default defineConfig({
oxc: {
jsxInject: `import React from 'react'`,
jsx: {
pragma: 'h',
pragmaFrag: 'Fragment',
},
},
})

选项映射表

esbuildoxc
jsxInjectjsxInject
includeinclude
excludeexclude
jsx: 'preserve'jsx: 'preserve'
jsx: 'automatic'jsx: { runtime: 'automatic' }
jsxImportSourcejsx.importSource
jsx: 'transform'jsx: { runtime: 'classic' }
jsxFactoryjsx.pragma
jsxFragmentjsx.pragmaFrag
jsxDevjsx.development
jsxSideEffectsjsx.pure
definedefine

JavaScript 压缩迁移

Oxc Minifier 现在用于 JavaScript 压缩。

如果需要回退到 esbuild 压缩

export default defineConfig({
build: {
minify: 'esbuild',
},
})

注意:使用 esbuild 压缩需要单独安装 esbuild:

npm install -D esbuild

压缩选项迁移

如果你之前使用 esbuild.drop 移除 console 和 debugger:

// 旧配置
export default defineConfig({
esbuild: {
drop: ['console', 'debugger'],
},
})

// 新配置
export default defineConfig({
build: {
rolldownOptions: {
output: {
minify: {
compress: {
dropConsole: true,
dropDebugger: true,
},
},
},
},
},
})

CSS 压缩迁移

Lightning CSS 现在用于 CSS 压缩。

如果需要回退到 esbuild 压缩 CSS

export default defineConfig({
build: {
cssMinify: 'esbuild',
},
})

注意:Lightning CSS 支持更好的语法降级,但可能会导致 CSS 包体积略有增加。

CommonJS 互操作变更

Vite 8 对 CommonJS 模块的 default 导入处理方式更加一致。这可能会影响一些现有代码。

变更说明

如果满足以下任一条件,default 导入是 CJS 模块的 module.exports 值:

  • 导入方是 .mjs.mts 文件
  • 导入方最近的 package.json 设置了 type: "module"
  • CJS 模块的 module.exports.__esModule 未设为 true

否则,default 导入是 module.exports.default 值。

如果遇到问题

可以临时启用兼容模式:

export default defineConfig({
legacy: {
inconsistentCjsInterop: true,
},
})

但建议尽快修复代码,因为此选项将在未来移除。

废弃的配置选项

以下选项已被废弃,需要迁移:

build.rollupOptions → build.rolldownOptions

// 旧配置
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router'],
},
},
},
},
})

// 新配置
export default defineConfig({
build: {
rolldownOptions: {
output: {
advancedChunks: {
groups: [
{ name: 'vendor', test: /\/(vue|vue-router)\// },
],
},
},
},
},
})

build.commonjsOptions

此选项现在无效,CommonJS 转换由 Rolldown 自动处理。

worker.rollupOptions → worker.rolldownOptions

// 旧配置
export default defineConfig({
worker: {
rollupOptions: {
output: {
entryFileNames: 'worker-[name].js',
},
},
},
})

// 新配置
export default defineConfig({
worker: {
rolldownOptions: {
output: {
entryFileNames: 'worker-[name].js',
},
},
},
})

resolve.alias[].customResolver

使用带有 enforce: 'pre' 的自定义插件替代:

// 旧配置
export default defineConfig({
resolve: {
alias: [
{
find: '@',
replacement: '/src',
customResolver: myResolver,
},
],
},
})

// 新配置
export default defineConfig({
plugins: [
{
name: 'custom-resolver',
enforce: 'pre',
resolveId(source, importer) {
if (source.startsWith('@')) {
// 自定义解析逻辑
}
},
},
],
})

移除的功能

build.rollupOptions.output.manualChunks 对象形式

对象形式的 manualChunks 已不再支持:

// ❌ 不再支持
manualChunks: {
vendor: ['vue', 'vue-router'],
}

// ⚠️ 函数形式已废弃,但仍可用
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor'
}
}

// ✅ 推荐使用 advancedChunks
advancedChunks: {
groups: [
{ name: 'vendor', test: /node_modules/ },
],
}

import.meta.hot.accept 传入 URL

不再支持向 import.meta.hot.accept 传入 URL,应传入模块 ID:

// ❌ 不再支持
import.meta.hot.accept('/src/utils.js', (module) => {
// ...
})

// ✅ 正确用法
import.meta.hot.accept('./utils.js', (module) => {
// ...
})

不支持的输出格式

以下输出格式不再支持:

  • format: 'system'
  • format: 'amd'

移除的 Rollup 钩子

以下 Rollup 钩子不再支持:

  • shouldTransformCachedModule
  • resolveImportMeta
  • renderDynamicImport
  • resolveFileUrl

插件开发者注意事项

moduleType 支持

Rolldown 支持模块类型,会根据文件扩展名自动检测。如果在 loadtransform 钩子中将其他类型转换为 JavaScript,需要明确指定:

const plugin = {
name: 'txt-loader',
load(id) {
if (id.endsWith('.txt')) {
const content = fs.readFileSync(id, 'utf-8')
return {
code: `export default ${JSON.stringify(content)}`,
moduleType: 'js', // 必须明确指定
}
}
},
}

transformWithEsbuild 迁移

transformWithEsbuild 函数已废弃,需要迁移到 transformWithOxc

import { transformWithOxc } from 'vite'

const result = await transformWithOxc(code, {
loader: 'ts',
target: 'es2020',
})

如果仍需使用 transformWithEsbuild,需要单独安装 esbuild:

npm install -D esbuild

build() 错误处理

build() 现在抛出 BundleError 而不是原始错误:

try {
await build()
} catch (e) {
if (e.errors) {
for (const error of e.errors) {
console.log(error.code)
}
}
}

原生装饰器处理

Oxc 目前不支持降级原生装饰器。如果需要使用装饰器,可以使用 Babel 或 SWC 进行转换。

使用 Babel

npm install -D @rolldown/plugin-babel @babel/plugin-proposal-decorators
import { defineConfig } from 'vite'
import babel from '@rolldown/plugin-babel'

function decoratorPreset(options) {
return {
preset: () => ({
plugins: [['@babel/plugin-proposal-decorators', options]],
}),
rolldown: {
filter: { code: '@' }, // 仅当文件包含装饰器时转换
},
}
}

export default defineConfig({
plugins: [
babel({ presets: [decoratorPreset({ version: '2023-11' })] }),
],
})

使用 SWC

npm install -D @rollup/plugin-swc @swc/core
import { defineConfig, withFilter } from 'vite'
import swc from '@rollup/plugin-swc'

export default defineConfig({
plugins: [
withFilter(
swc({
swc: {
jsc: {
parser: { decorators: true, decoratorsBeforeExport: true },
transform: { decoratorVersion: '2023-11' },
},
},
}),
{ transform: { code: '@' } },
),
],
})

require 调用处理

对于外部化模块的 require 调用,现在会保留为 require 而不是转换为 import

如果需要转换为 import,可以使用内置插件:

import { defineConfig, esmExternalRequirePlugin } from 'vite'

export default defineConfig({
plugins: [
esmExternalRequirePlugin({
external: ['react', 'vue', /^node:/],
}),
],
})

迁移检查清单

完成迁移后,请检查以下项目:

  • Node.js 版本满足要求(20.19+ 或 22.12+)
  • 所有废弃的配置选项已更新
  • 构建命令正常执行
  • 开发服务器正常启动
  • HMR 正常工作
  • 生产构建输出正确
  • 所有测试通过
  • 没有弃用警告

常见问题

esbuild 相关错误

如果看到 Cannot find module 'esbuild' 错误:

npm install -D esbuild

Rolldown 选项验证警告

如果看到未知选项警告,检查是否使用了 Rollup 特有的选项。移除或替换这些选项。

压缩后代码不工作

如果压缩后代码出现问题,尝试:

  1. 临时禁用压缩定位问题
  2. 检查是否使用了 Oxc 不支持的语法
  3. 提交 issue 到 Vite 仓库

CommonJS 导入问题

如果遇到 default 导入为 undefined 的问题:

  1. 检查导入方式是否正确
  2. 尝试使用命名导入
  3. 临时启用 legacy.inconsistentCjsInterop

获取帮助

如果在迁移过程中遇到问题:

  1. 查看 Vite GitHub Discussions
  2. 加入 Vite Discord 社区
  3. 提交 GitHub Issue

提供最小复现示例可以帮助更快解决问题。