Vite 8 迁移指南
如果你正在从 Vite 7 升级到 Vite 8,本指南将帮助你了解主要变更和迁移步骤。Vite 8 是一个重要版本,引入了 Rolldown 作为统一打包器,这带来了一些破坏性变更。
升级前准备
在开始迁移之前,建议先完成以下准备工作:
- 确保你的项目使用 Vite 7 的最新版本
- 查看 Vite 7 的弃用警告,提前处理这些问题
- 在单独的分支上进行迁移测试
- 准备好回滚方案
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 7 | Vite 8 |
|---|---|---|
| Chrome | 107 | 111 |
| Edge | 107 | 111 |
| Firefox | 104 | 114 |
| Safari | 16.0 | 16.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',
},
},
})
选项映射表:
| esbuildOptions | 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(部分支持) |
Vite 仍会自动转换 esbuildOptions 到 rolldownOptions,但建议尽早迁移。
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',
},
},
})
选项映射表:
| esbuild | oxc |
|---|---|
jsxInject | jsxInject |
include | include |
exclude | exclude |
jsx: 'preserve' | jsx: 'preserve' |
jsx: 'automatic' | jsx: { runtime: 'automatic' } |
jsxImportSource | jsx.importSource |
jsx: 'transform' | jsx: { runtime: 'classic' } |
jsxFactory | jsx.pragma |
jsxFragment | jsx.pragmaFrag |
jsxDev | jsx.development |
jsxSideEffects | jsx.pure |
define | define |
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 钩子不再支持:
shouldTransformCachedModuleresolveImportMetarenderDynamicImportresolveFileUrl
插件开发者注意事项
moduleType 支持
Rolldown 支持模块类型,会根据文件扩展名自动检测。如果在 load 或 transform 钩子中将其他类型转换为 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 特有的选项。移除或替换这些选项。
压缩后代码不工作
如果压缩后代码出现问题,尝试:
- 临时禁用压缩定位问题
- 检查是否使用了 Oxc 不支持的语法
- 提交 issue 到 Vite 仓库
CommonJS 导入问题
如果遇到 default 导入为 undefined 的问题:
- 检查导入方式是否正确
- 尝试使用命名导入
- 临时启用
legacy.inconsistentCjsInterop
获取帮助
如果在迁移过程中遇到问题:
- 查看 Vite GitHub Discussions
- 加入 Vite Discord 社区
- 提交 GitHub Issue
提供最小复现示例可以帮助更快解决问题。