从 v4 迁移
Node.js 支持
Vite 不再支持 Node.js 14 / 16 / 17 / 19,因为它们已经到了 EOL。现在需要 Node.js 18 / 20+。
Rollup 4
Vite 现在使用 Rollup 4,它也带来了一些重大的变化,特别是:
- 导入断言(
assertions
属性)已被重命名为导入属性(attributes
属性)。 - 不再支持 Acorn 插件。
- 对于 Vite 插件,
this.resolve
的skipSelf
选项现在默认为true
。 - 对于 Vite 插件,
this.parse
现在只支持allowReturnOutsideFunction
选项。
Invalid code snippet option
你可以阅读 Rollup 的发布说明 中的破坏性变更,了解在 build.rollupOptions
中构建相关的变更。
Read the full breaking changes in Rollup's release notes for build-related changes in build.rollupOptions
.
cb28b1ffb3de626548c59cb2211f8f1cdfcd07d0
废弃 CJS Node API
CJS 的 Node API 已经被废弃。当调用 require('vite')
时,将会记录一个废弃警告。你应该更新你的文件或框架来导入 Vite 的 ESM 构建。
在一个基础的 Vite 项目中,请确保:
vite.config.js
配置文件的内容使用 ESM 语法。- 最近的
package.json
文件中有"type": "module"
,或者使用.mjs
扩展名,例如vite.config.mjs
。
对于其他项目,有几种常见的方法:
- 配置 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.*
的替换策略
Invalid code snippet option
在 Vite 4 中,define
和 import.meta.env.*
特性在开发和构建中使用的是不同的替换策略:
In Vite 4, the define
and i
features use different replacement strategies in dev and build:
cb28b1ffb3de626548c59cb2211f8f1cdfcd07d0
- 在开发时,这两个特性分别作为全局变量注入到
globalThis
和i
中。mport.meta - 在构建时,这两个特性都使用正则表达式进行静态替换。
这导致在尝试访问这些变量时,开发和构建存在一致性问题,有时甚至导致构建失败。例如:
// vite.config.js
export default defineConfig({
define: {
__APP_VERSION__: JSON.stringify('1.0.0'),
},
})
const data = { __APP_VERSION__ }
// 开发:{ __APP_VERSION__: "1.0.0" } ✅
// 构建:{ "1.0.0" } ❌
const docs = 'I like import.meta.env.MODE '
// 开发:"I like import.meta.env.MODE" ✅
// 构建:"I like "production"" ❌
Vite 5 通过在构建中使用 esbuild
来处理替换,使其与开发行为保持一致。
这个改动不应该影响大部分设置,因为已经在文档中说明了 define
的值应该遵循 esbuild 的语法:
为了与 esbuild 行为保持一致,表达式必须是一个 JSON 对象(null、boolean、number、string、array 或 object)或一个单一标识符字符串。
然而,如果你更喜欢对值直接使用静态替换,你可以使用 @rollup/plugin-replace
。
其他一般性变化
SSR 外部模块值现在符合生产环境行为
在 Vite 4 中,服务器端渲染的外部模块被包装为 .default
和 .__esModule
处理,以实现更好的互操作性,但是它并不符合运行时环境(例如 Node.js)加载时的生产环境行为,导致难以捕获的不一致性。默认情况下,所有直接的项目依赖都是 SSR 外部化的。
Vite 5 现在删除了 .default
和 .__esModule
处理,以匹配生产环境行为。在实践中,这不应影响正确打包的依赖项,但是如果你在加载模块时遇到新的问题,你可以尝试以下重构:
// 之前:
import { foo } from 'bar'
// 之后:
import _bar from 'bar'
const { foo } = _bar
// 之前:
import foo from 'bar'
// 之后:
import * as _foo from 'bar'
const foo = _foo.default
注意,这些更改符合 Node.js 的行为,因此也可以在 Node.js 中运行这些导入进行测试。如果你更喜欢坚持使用之前的方式,你可以将 legacy.proxySsrExternalModules
设置为 true
。
worker.plugins
现在是一个函数
Invalid code snippet option
在 Vite 4 中,worker.plugins
接受一个插件数组 ((Plugin | Plugin[])[]
)。从 Vite 5 开始,它需要配置为一个返回插件数组的函数 (() => (Plugin | Plugin[])[]
)。这个改变是为了让并行的 worker 构建运行得更加一致和可预测。
In Vite 4, worker.plugins
accepted an array of plugins ((Plugin | Plugin[])[]
). From Vite 5, it needs to be configured as a function that returns an array of plugins (() => (Plugin | Plugin[])[]
). This change is required so parallel worker builds run more consistently and predictably.
cb28b1ffb3de626548c59cb2211f8f1cdfcd07d0
允许路径包含 .
回退到 index.html
Invalid code snippet option
在 Vite 4 中,即使 appType
被设置为 'SPA'
(默认),访问包含 .
的路径也不会回退到 index.html。从 Vite 5 开始,它将会回退到 index.html。
注意浏览器将不再在控制台中显示 404 错误消息,如果你将图片路径指向一个不存在的文件(例如 <img src="./file-does-not-exist.png">
)。
In Vite 4, accessing a path in dev containing .
did not fallback to index.html even if appType
is set to 'spa'
(default). From Vite 5, it will fallback to index.html.
Note that the browser will no longer show a 404 error message in the console if you point the image path to a non-existent file (e.g. <img src="./file-does-not-exist.png">
).
Align dev and preview HTML serving behaviour
In Vite 4, the dev and preview servers serve HTML based on its directory structure and trailing slash differently. This causes inconsistencies when testing your built app. Vite 5 refactors into a single behaviour like below, given the following file structure:
├── index.html
├── file.html
└── dir
└── index.html
Request | Before (dev) | Before (preview) | After (dev & preview) |
---|---|---|---|
/dir/index.html | /dir/index.html | /dir/index.html | /dir/index.html |
/dir | /index.html (SPA fallback) | /dir/index.html | /dir.html (SPA fallback) |
/dir/ | /dir/index.html | /dir/index.html | /dir/index.html |
/file.html | /file.html | /file.html | /file.html |
/file | /index.html (SPA fallback) | /file.html | /file.html |
/file/ | /index.html (SPA fallback) | /file.html | /index.html (SPA fallback) |
cb28b1ffb3de626548c59cb2211f8f1cdfcd07d0
Manifest 文件现在默认生成到 .vite
目录中
Invalid code snippet option
在 Vite 4 中,manifest 文件(build.manifest
,build.ssrManifest
)默认会生成在 build.outDir
的根目录中。从 Vite 5 开始,这些文件将默认生成在 build.outDir
中的 .vite
目录中。
In Vite 4, the manifest files (build.manifest
, build.ssrManifest
) was generated in the root of build.outDir
by default. From Vite 5, those will be generated in the .vite
directory in the build.outDir
by default.
cb28b1ffb3de626548c59cb2211f8f1cdfcd07d0
CLI 快捷功能键需要一个额外的 Enter
按键
CLI 快捷功能键,例如 r
重启开发服务器,现在需要额外的 Enter
按键来触发快捷功能。例如,r + Enter
重启开发服务器。
这个改动防止 Vite 吞噬和控制操作系统特定的快捷键,允许更好的兼容性,当将 Vite 开发服务器与其他进程结合使用时,并避免了之前的注意事项。
Invalid code snippet option
移除 --https
标志和 https: true
=======
Update experimentalDecorators
and useDefineForClassFields
TypeScript behaviour
Vite 5 uses esbuild 0.19 and removes the compatibility layer for esbuild 0.18, which changes how experimentalDecorators
and useDefineForClassFields
are handled.
experimentalDecorators
is not enabled by defaultYou need to set
compilerOptions.experimentalDecorators
totrue
intsconfig.json
to use decorators.useDefineForClassFields
defaults depend on the TypeScripttarget
valueIf
target
is notESNext
orES2022
or newer, or if there's notsconfig.json
file,useDefineForClassFields
will default tofalse
which can be problematic with the defaultesbuild.target
value ofesnext
. It may transpile to static initialization blocks which may not be supported in your browser.As such, it is recommended to set
target
toESNext
orES2022
or newer, or setuseDefineForClassFields
totrue
explicitly when configuringtsconfig.json
.
{
"compilerOptions": {
// Set true if you use decorators
"experimentalDecorators": true,
// Set true if you see parsing errors in your browser
"useDefineForClassFields": true
}
}
Remove --https
flag and https: true
cb28b1ffb3de626548c59cb2211f8f1cdfcd07d0
--https
标志设置 https: true
。这个配置本来是要与自动 https 证书生成特性一起使用的,但这个特性在 Vite 3 中被移除。这个配置现在已经没有意义了,因为它会让Vite启动一个没有证书的 HTTPS 服务器。 @vitejs/plugin-basic-ssl
和 vite-plugin-mkcert
都会设置 https
配置,无论 https
值是什么,所以你可以直接移除 --https
和 https: true
。
移除 resolvePackageEntry
和 resolvePackageData
API
resolvePackageEntry
和 resolvePackageData
API 已被移除,因为它们暴露了 Vite 的内部机制,并在过去阻碍了 Vite 4.3 的潜在优化。这些 API 可以被第三方包替代,例如:
resolvePackageEntry
:i
或者mport.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
Invalid code snippet option
- CSS 文件的默认导出(例如
import style from './foo.css'
):使用?inline
查询参数代替 i
:使用mport.meta.globEager i
来代替mport.meta.glob('*', { eager: true }) ssr.format: 'cjs'
和legacy.buildSsrCjsExternalHeuristics
(#13816) =======- Default exports of CSS files (e.g
import style from './foo.css'
): Use the?inline
query instead i
: Usemport.meta.globEager i
insteadmport.meta.glob('*', { eager: true }) ssr.format: 'cjs'
andlegacy.buildSsrCjsExternalHeuristics
(#13816)server.middlewareMode: 'ssr'
andserver.middlewareMode: 'html'
: UseappType
+server.middlewareMode: true
instead (#8452)
cb28b1ffb3de626548c59cb2211f8f1cdfcd07d0
进阶
下列改动仅会影响到插件/工具的作者:
- [#14119] refactor!: merge
PreviewServerForHook
intoPreviewServer
type- The
configurePreviewServer
hook now accepts thePreviewServer
type instead ofPreviewServerForHook
type.
- The
- [#14818] refactor(preview)!: use base middleware
- Middlewares added from the returned function in
configurePreviewServer
now does not have access to thebase
when comparing thereq.url
value. This aligns the behaviour with the dev server. You can check thebase
from theconfigResolved
hook if needed.
- Middlewares added from the returned function in
此外,还有其他一些只影响少数用户的破坏性变化。
- [#14098] fix!: avoid rewriting this (reverts #5312)
- 之前顶层
this
将会在构建时被默认地改写为globalThis
,这个行为现在已被移除
- 之前顶层
- [#14231] feat!: add extension to internal virtual modules
- 内置虚拟模块的 id 现在包含一个扩展名(
.js
)
- 内置虚拟模块的 id 现在包含一个扩展名(
- [#14583] refactor!: remove exporting internal APIs
- 移除意外导出的内部 API:
isDepsOptimizerEnabled
和getDepOptimizationConfig
- 移除导出的内部类型:
DepOptimizationResult
,DepOptimizationProcessing
和DepsOptimizer
- 改名
ResolveWorkerOptions
类型为ResolvedWorkerOptions
- 移除意外导出的内部 API:
- [#5657] fix: return 404 for resources requests outside the base path
- 过去,Vite 对于不带
Accept: text/html
的请求,会将其当作带有基础路径的请求来处理。现在 Vite 不再这样做,而是返回 404。
- 过去,Vite 对于不带
- [#14723] fix(resolve)!: remove special .mjs handling
- 在过去,当一个库的
"exports"
字段映射到一个.mjs
文件时,Vite 仍然会尝试匹配"browser"
和"module"
字段,以修复与某些库的兼容性。现在,这种行为已被移除,以便与导出解析算法保持一致。
- 在过去,当一个库的
- [#14733] feat(resolve)!: remove
resolve.browserField
<<<<<<< HEADresolve.browserField
has been deprecated since Vite 3 in favour of an updated default of['browser', 'module', 'jsnext:main', 'jsnext']
forresolve.mainFields
。 =======resolve.browserField
has been deprecated since Vite 3 in favour of an updated default of['browser', 'module', 'jsnext:main', 'jsnext']
forresolve.mainFields
.
- [#14855] feat!: add isPreview to ConfigEnv and resolveConfig
- Renamed
ssrBuild
toisSsrBuild
in theConfigEnv
object.
- Renamed
cb28b1ffb3de626548c59cb2211f8f1cdfcd07d0
从 v3 迁移
请先查看 从 v3 迁移指南 文档查看对您的应用所有需要迁移的改动,然后再执行本篇指南所述的改动。