从 v4 迁移
Node.js 支持
Vite 不再支持 Node.js 14 / 16 / 17 / 19,这些版本已达到生命周期结束。现在需要 Node.js 18 / 20+。
Rollup 4
Vite 现在使用 Rollup 4,这也带来了它的重大更改,特别是
- 导入断言 (
assertions
属性) 已重命名为导入属性 (attributes
属性)。 - 不再支持 Acorn 插件。
- 对于 Vite 插件,
this.resolve
的skipSelf
选项现在默认值为true
。 - 对于 Vite 插件,
this.parse
现在只支持allowReturnOutsideFunction
选项。
阅读 Rollup 的发布说明 中的完整重大更改,了解与构建相关的更改,这些更改在 build.rollupOptions
中。
如果您使用的是 TypeScript,请确保将 moduleResolution
设置为 'bundler'
(或 node16
/nodenext
),因为 Rollup 4 需要它。或者,您可以改为设置 skipLibCheck: true
。
弃用 CJS Node API
Vite 的 CJS Node API 已弃用。当调用 require('vite')
时,现在会记录弃用警告。您应该更新您的文件或框架以改为导入 Vite 的 ESM 构建。
在一个基本的 Vite 项目中,请确保
vite.config.js
文件内容使用 ESM 语法。- 最接近的
package.json
文件具有"type": "module"
,或者使用.mjs
/.mts
扩展名,例如vite.config.mjs
或vite.config.mts
。
对于其他项目,有几种通用的方法
- 将 ESM 配置为默认值,并在需要时选择加入 CJS:在项目
package.json
中添加"type": "module"
。现在所有*.js
文件都被解释为 ESM,并且需要使用 ESM 语法。您可以将文件重命名为.cjs
扩展名以继续使用 CJS。 - 将 CJS 配置为默认值,并在需要时选择加入 ESM:如果项目
package.json
没有"type": "module"
,所有*.js
文件都被解释为 CJS。您可以将文件重命名为.mjs
扩展名以改为使用 ESM。 - 动态导入 Vite:如果您需要继续使用 CJS,您可以使用
import('vite')
动态导入 Vite。这需要您的代码在async
上下文中编写,但由于 Vite 的 API 主要是异步的,因此仍然可以管理。
有关更多信息,请参阅 故障排除指南。
重新设计 define
和 import.meta.env.*
替换策略
在 Vite 4 中,define
和 import.meta.env.*
功能在开发和构建中使用不同的替换策略
- 在开发中,这两个功能分别作为全局变量注入到
globalThis
和import.meta
中。 - 在构建中,这两个功能使用正则表达式进行静态替换。
这会导致在尝试访问变量时出现开发和构建不一致,有时甚至会导致构建失败。例如
// vite.config.js
export default defineConfig({
define: {
__APP_VERSION__: JSON.stringify('1.0.0'),
},
})
const data = { __APP_VERSION__ }
// dev: { __APP_VERSION__: "1.0.0" } ✅
// build: { "1.0.0" } ❌
const docs = 'I like import.meta.env.MODE'
// dev: "I like import.meta.env.MODE" ✅
// build: "I like "production"" ❌
Vite 5 通过使用 esbuild
处理构建中的替换来修复此问题,使其与开发行为保持一致。
此更改不应影响大多数设置,因为它已在文档中说明 define
值应遵循 esbuild 的语法
为了与 esbuild 行为保持一致,表达式必须是 JSON 对象(null、布尔值、数字、字符串、数组或对象)或单个标识符。
但是,如果您希望直接静态替换值,可以使用 @rollup/plugin-replace
。
一般更改
SSR 外部化模块值现在与生产环境匹配
在 Vite 4 中,SSR 外部化模块使用 .default
和 .__esModule
处理进行包装,以实现更好的互操作性,但它与运行时环境(例如 Node.js)加载时的生产行为不匹配,导致难以发现的不一致。默认情况下,所有直接项目依赖项都是 SSR 外部化的。
Vite 5 现在删除了 .default
和 .__esModule
处理以匹配生产行为。在实践中,这不会影响正确打包的依赖项,但如果您遇到加载模块的新问题,可以尝试以下重构
// Before:
import { foo } from 'bar'
// After:
import _bar from 'bar'
const { foo } = _bar
// Before:
import foo from 'bar'
// After:
import * as _foo from 'bar'
const foo = _foo.default
请注意,这些更改与 Node.js 行为匹配,因此您也可以在 Node.js 中运行导入以进行测试。如果您希望坚持使用以前的 behavior,可以将 legacy.proxySsrExternalModules
设置为 true
。
worker.plugins
现在是一个函数
在 Vite 4 中,worker.plugins
接受一个插件数组 ((Plugin | Plugin[])[]
)。从 Vite 5 开始,它需要配置为一个返回插件数组的函数 (() => (Plugin | Plugin[])[]
)。此更改是必需的,以便并行工作程序构建更一致且可预测地运行。
允许包含 .
的路径回退到 index.html
在 Vite 4 中,在开发中访问包含 .
的路径不会回退到 index.html,即使 appType
设置为 'spa'
(默认值)。从 Vite 5 开始,它将回退到 index.html。
请注意,如果您将图像路径指向不存在的文件(例如 <img src="./file-does-not-exist.png">
),浏览器将不再在控制台中显示 404 错误消息。
使开发和预览 HTML 服务行为保持一致
在 Vite 4 中,开发和预览服务器根据其目录结构和尾部斜杠的不同方式提供 HTML。这在测试构建的应用程序时会导致不一致。Vite 5 将其重构为以下单一行为,假设以下文件结构
├── index.html
├── file.html
└── dir
└── index.html
请求 | 之前(开发) | 之前(预览) | 之后(开发和预览) |
---|---|---|---|
/dir/index.html | /dir/index.html | /dir/index.html | /dir/index.html |
/dir | /index.html (SPA 回退) | /dir/index.html | /index.html (SPA 回退) |
/dir/ | /dir/index.html | /dir/index.html | /dir/index.html |
/file.html | /file.html | /file.html | /file.html |
/file | /index.html (SPA 回退) | /file.html | /file.html |
/file/ | /index.html (SPA 回退) | /file.html | /index.html (SPA 回退) |
清单文件现在默认情况下在 .vite
目录中生成
在 Vite 4 中,清单文件(build.manifest
和 build.ssrManifest
)默认情况下在 build.outDir
的根目录中生成。
从 Vite 5 开始,它们将默认情况下在 build.outDir
中的 .vite
目录中生成。此更改有助于在将公共文件复制到 build.outDir
时,避免与相同清单文件名发生冲突。
相应的 CSS 文件未在 manifest.json 文件中列为顶级条目
在 Vite 4 中,JavaScript 入口点的相应 CSS 文件也作为清单文件(build.manifest
)中的顶级条目列出。这些条目是无意中添加的,并且仅适用于简单情况。
在 Vite 5 中,相应的 CSS 文件只能在 JavaScript 入口文件部分中找到。在注入 JS 文件时,相应的 CSS 文件 应该被注入。当需要单独注入 CSS 时,必须将其添加为单独的入口点。
CLI 快捷方式需要额外按一次 Enter
键
CLI 快捷方式,例如 r
重新启动开发服务器,现在需要额外按一次 Enter
键才能触发快捷方式。例如,r + Enter
重新启动开发服务器。
此更改可防止 Vite 吞下并控制特定于操作系统的快捷方式,从而在将 Vite 开发服务器与其他进程结合使用时实现更好的兼容性,并避免 以前的注意事项。
更新 experimentalDecorators
和 useDefineForClassFields
TypeScript 行为
Vite 5 使用 esbuild 0.19 并删除了 esbuild 0.18 的兼容性层,这改变了 experimentalDecorators
和 useDefineForClassFields
的处理方式。
experimentalDecorators
默认情况下未启用您需要在
tsconfig.json
中将compilerOptions.experimentalDecorators
设置为true
才能使用装饰器。useDefineForClassFields
默认值取决于 TypeScript 的target
值如果
target
不是ESNext
或ES2022
或更高版本,或者没有tsconfig.json
文件,useDefineForClassFields
将默认为false
,这在使用esbuild.target
的默认值esnext
时可能会出现问题。它可能会转译为 静态初始化块,这些块可能不受您的浏览器支持。因此,建议将
target
设置为ESNext
或ES2022
或更高版本,或者在配置tsconfig.json
时显式地将useDefineForClassFields
设置为true
。
{
"compilerOptions": {
// Set true if you use decorators
"experimentalDecorators": true,
// Set true if you see parsing errors in your browser
"useDefineForClassFields": true,
},
}
删除 --https
标志和 https: true
--https
标志在内部设置 server.https: true
和 preview.https: true
。此配置旨在与自动 https 证书生成功能一起使用,该功能 在 Vite 3 中被删除。因此,此配置不再有用,因为它将在没有证书的情况下启动 Vite HTTPS 服务器。
如果您使用 @vitejs/plugin-basic-ssl
或 vite-plugin-mkcert
,它们将在内部设置 https
配置,因此您可以在设置中删除 --https
、server.https: true
和 preview.https: true
。
删除 resolvePackageEntry
和 resolvePackageData
API
resolvePackageEntry
和 resolvePackageData
API 被删除,因为它们暴露了 Vite 的内部机制,并在过去阻止了潜在的 Vite 4.3 优化。这些 API 可以用第三方包替换,例如
resolvePackageEntry
:import.meta.resolve
或import-meta-resolve
包。resolvePackageData
:与上面相同,并向上遍历包目录以获取根package.json
。或者使用社区vitefu
包。
import { resolve } from 'import-meta-env'
import { findDepPkgJsonPath } from 'vitefu'
import fs from 'node:fs'
const pkg = 'my-lib'
const basedir = process.cwd()
// `resolvePackageEntry`:
const packageEntry = resolve(pkg, basedir)
// `resolvePackageData`:
const packageJsonPath = findDepPkgJsonPath(pkg, basedir)
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))
已删除的已弃用 API
- CSS 文件的默认导出(例如
import style from './foo.css'
):使用?inline
查询代替 import.meta.globEager
:使用import.meta.glob('*', { eager: true })
代替ssr.format: 'cjs'
和legacy.buildSsrCjsExternalHeuristics
(#13816)server.middlewareMode: 'ssr'
和server.middlewareMode: 'html'
:使用appType
+server.middlewareMode: true
代替 (#8452)
高级
有一些更改只会影响插件/工具创建者。
- [#14119] refactor!: 将
PreviewServerForHook
合并到PreviewServer
类型中configurePreviewServer
钩子现在接受PreviewServer
类型而不是PreviewServerForHook
类型。
- [#14818] refactor(preview)!: 使用基本中间件
- 从
configurePreviewServer
中返回的函数中添加的中间件现在在比较req.url
值时无法访问base
。这与开发服务器的行为保持一致。如果需要,您可以从configResolved
钩子中检查base
。
- 从
- [#14834] fix(types)!: 使用 Http2SecureServer 联合公开 httpServer
- 现在在适当的地方使用
http.Server | http2.Http2SecureServer
代替http.Server
。
- 现在在适当的地方使用
此外,还有一些其他重大更改,这些更改只会影响少数用户。
- [#14098] fix!: 避免重写 this(恢复 #5312)
- 在构建时,默认情况下将顶级
this
重写为globalThis
。此行为现已删除。
- 在构建时,默认情况下将顶级
- [#14231] feat!: 向内部虚拟模块添加扩展名
- 内部虚拟模块的 ID 现在具有扩展名(
.js
)。
- 内部虚拟模块的 ID 现在具有扩展名(
- [#14583] refactor!: 删除导出内部 API
- 删除了意外导出的内部 API:
isDepsOptimizerEnabled
和getDepOptimizationConfig
- 删除了导出的内部类型:
DepOptimizationResult
、DepOptimizationProcessing
和DepsOptimizer
- 将
ResolveWorkerOptions
类型重命名为ResolvedWorkerOptions
- 删除了意外导出的内部 API:
- [#5657] fix: 对基本路径之外的资源请求返回 404
- 在过去,Vite 会响应基本路径之外的请求,而不会使用
Accept: text/html
,就好像它们是使用基本路径请求的一样。Vite 现在不再这样做,而是返回 404。
- 在过去,Vite 会响应基本路径之外的请求,而不会使用
- [#14723] fix(resolve)!: 删除特殊的 .mjs 处理
- 在过去,当库的
"exports"
字段映射到.mjs
文件时,Vite 仍然会尝试匹配"browser"
和"module"
字段以修复与某些库的兼容性。此行为现已删除,以与导出解析算法保持一致。
- 在过去,当库的
- [#14733] feat(resolve)!: 删除
resolve.browserField
resolve.browserField
自 Vite 3 以来已弃用,取而代之的是resolve.mainFields
的更新默认值['browser', 'module', 'jsnext:main', 'jsnext']
。
- [#14855] feat!: 向 ConfigEnv 和 resolveConfig 添加 isPreview
- 将
ConfigEnv
对象中的ssrBuild
重命名为isSsrBuild
。
- 将
- [#14945] fix(css): 正确设置清单源名称并发出 CSS 文件
- CSS 文件名现在根据块名生成。
从 v3 迁移
首先查看 Vite v4 文档中的 从 v3 迁移指南,以查看将您的应用程序移植到 Vite v4 所需的更改,然后继续进行此页面上的更改。