##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節點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:添加"type": "module"到項目中package.json。所有*.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__ }
// 開發:{ __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 來處理替換,使其與開發行爲保持一致。
##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 現在是一個函數
在 Vite 4 中,worker.plugins 接受一個插件數組 ((Plugin | Plugin[])[])。從 Vite 5 開始,它需要配置爲一個返回插件數組的函數 (() => (Plugin | Plugin[])[])。這個改變是爲了讓並行的 worker 構建運行得更加一致和可預測。
##允許路徑包含 . 回退到 index.html
在 Vite 4 中,即使 appType 被設置爲 'SPA'(默認),訪問包含 . 的路徑也不會回退到 index.html。從 Vite 5 開始,它將會回退到 index.html。
##調整開發和預覽 HTML 服務行爲
在 Vite 4 中,開發服務器和預覽服務器會根據 HTML 的目錄結構和尾部斜槓的不同來提供 HTML。這會導致在測試構建後的應用時出現不一致的情況。Vite 5 重構成了一個單一的行爲,如下所示,給定以下文件結構:
├── index.html
├── file.html
└── dir
└── index.html
請求 | 過往版本 (dev) | 過往版本 (preview) | 現在 (dev & preview) |
---|---|---|---|
/dir/index.html | /dir/index.html | /dir/index.html | /dir/index.html |
/dir | /index.html (SPA fallback) | /dir/index.html | /index.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) |
##Manifest 文件現在默認生成到 .vite 目錄中
在 Vite 4 中,manifest 文件(build.manifest,build.ssrManifest)默認會生成在 build.outDir 的根目錄中。
從 Vite 5 開始,這些文件將默認生成在 build.outDir 中的 .vite 目錄中。這個改變有助於解決當公共文件被複制到 build.outDir 時,具有相同 manifest 文件名時的衝突。
##CLI 快捷功能鍵需要一個額外的 Enter 按鍵
CLI 快捷功能鍵,例如 r 重啓開發服務器,現在需要額外的 Enter 按鍵來觸發快捷功能。例如,r + Enter 可以重新開發服務器。
這個改動防止 Vite 吞噬和控制操作系統特定的快捷鍵,允許更好的兼容性,當將 Vite 開發服務器與其他進程結合使用時,並避免了之前的注意事項。
##移除 --https 標誌和 https: true
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)
##擴展鏈接