跳至内容

从 v4 迁移

Node.js 支持

Vite 不再支持 Node.js 14 / 16 / 17 / 19,这些版本已达到生命周期结束。现在需要 Node.js 18 / 20+。

Rollup 4

Vite 现在使用 Rollup 4,这也带来了它的重大更改,特别是

  • 导入断言 (assertions 属性) 已重命名为导入属性 (attributes 属性)。
  • 不再支持 Acorn 插件。
  • 对于 Vite 插件,this.resolveskipSelf 选项现在默认值为 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 项目中,请确保

  1. vite.config.js 文件内容使用 ESM 语法。
  2. 最接近的 package.json 文件具有 "type": "module",或者使用 .mjs/.mts 扩展名,例如 vite.config.mjsvite.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 主要是异步的,因此仍然可以管理。

有关更多信息,请参阅 故障排除指南

重新设计 defineimport.meta.env.* 替换策略

在 Vite 4 中,defineimport.meta.env.* 功能在开发和构建中使用不同的替换策略

  • 在开发中,这两个功能分别作为全局变量注入到 globalThisimport.meta 中。
  • 在构建中,这两个功能使用正则表达式进行静态替换。

这会导致在尝试访问变量时出现开发和构建不一致,有时甚至会导致构建失败。例如

js
// vite.config.js
export default defineConfig({
  define: {
    __APP_VERSION__: JSON.stringify('1.0.0'),
  },
})
js
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 处理以匹配生产行为。在实践中,这不会影响正确打包的依赖项,但如果您遇到加载模块的新问题,可以尝试以下重构

js
// Before:
import { foo } from 'bar'

// After:
import _bar from 'bar'
const { foo } = _bar
js
// 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.manifestbuild.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 开发服务器与其他进程结合使用时实现更好的兼容性,并避免 以前的注意事项

更新 experimentalDecoratorsuseDefineForClassFields TypeScript 行为

Vite 5 使用 esbuild 0.19 并删除了 esbuild 0.18 的兼容性层,这改变了 experimentalDecoratorsuseDefineForClassFields 的处理方式。

  • experimentalDecorators 默认情况下未启用

    您需要在 tsconfig.json 中将 compilerOptions.experimentalDecorators 设置为 true 才能使用装饰器。

  • useDefineForClassFields 默认值取决于 TypeScript 的 target

    如果 target 不是 ESNextES2022 或更高版本,或者没有 tsconfig.json 文件,useDefineForClassFields 将默认为 false,这在使用 esbuild.target 的默认值 esnext 时可能会出现问题。它可能会转译为 静态初始化块,这些块可能不受您的浏览器支持。

    因此,建议将 target 设置为 ESNextES2022 或更高版本,或者在配置 tsconfig.json 时显式地将 useDefineForClassFields 设置为 true

jsonc
{
  "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: truepreview.https: true。此配置旨在与自动 https 证书生成功能一起使用,该功能 在 Vite 3 中被删除。因此,此配置不再有用,因为它将在没有证书的情况下启动 Vite HTTPS 服务器。

如果您使用 @vitejs/plugin-basic-sslvite-plugin-mkcert,它们将在内部设置 https 配置,因此您可以在设置中删除 --httpsserver.https: truepreview.https: true

删除 resolvePackageEntryresolvePackageData API

resolvePackageEntryresolvePackageData API 被删除,因为它们暴露了 Vite 的内部机制,并在过去阻止了潜在的 Vite 4.3 优化。这些 API 可以用第三方包替换,例如

js
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)

高级

有一些更改只会影响插件/工具创建者。

此外,还有一些其他重大更改,这些更改只会影响少数用户。

从 v3 迁移

首先查看 Vite v4 文档中的 从 v3 迁移指南,以查看将您的应用程序移植到 Vite v4 所需的更改,然后继续进行此页面上的更改。