Vite 5.0 正式發(fā)布,這是 Vite 道路上的又一個重要里程碑!
11 月 16 日,Vite 5.0 正式發(fā)布,這是 Vite 道路上的又一個重要里程碑!Vite 現(xiàn)在使用 Rollup 4,這已經(jīng)代表了構建性能的大幅提升。此外,還有一些新的選項可以改善開發(fā)服務器性能。
Vite 4 發(fā)布于近一年前,它為生態(tài)系統(tǒng)奠定了堅實的基礎。隨著項目繼續(xù)在共享基礎設施上構建,每周 npm 下載量從 250 萬躍升至 750 萬??蚣懿粩鄤?chuàng)新,除了 Astro、Nuxt、SvelteKit、Solid Start、Qwik City 等,還看到新的框架加入并使生態(tài)系統(tǒng)更加強大。RedwoodJS 和 Remix 轉向 Vite 為 React 生態(tài)系統(tǒng)的進一步采用鋪平了道路。Vitest 的增長速度甚至超過了 Vite。其團隊一直在努力,很快將發(fā)布 Vitest 1.0。Vite 與 Storybook、Nx 和 Playwright 等其他工具一起使用的故事不斷改進,環(huán)境也是如此,Vite 在 Deno 和 Bun 中都是可以使用的。
六個月前,Vite 4.3 版本發(fā)布。該版本顯著提高了開發(fā)服務器的性能。然而,仍有很大的改進空間。在 ViteConf 上,尤雨溪公布了 Vite 的長期計劃,即致力于開發(fā) Rolldown,這是一個帶有兼容 API 的 Rust 移植版的 Rollup。一旦準備就緒,打算在 Vite Core 中使用它來承擔 Rollup 和 esbuild 的任務。這將意味著提高構建性能,并大大減少開發(fā)和構建之間的不一致。Rolldown 目前處于早期階段,團隊正準備在年底前開源代碼庫。敬請關注!
Vite 5 專注于清理 API(刪除不推薦使用的功能),并簡化了解決長期問題的幾個功能,例如切換定義以使用正確的 AST 替換而不是 regex。團隊還將繼續(xù)采取措施來實現(xiàn)未來的 Vite(Node.js 18+ 現(xiàn)在是必需的,CJS Node API 已被棄用)。
# 快速開始使用 Vite 5
可以使用 pnpm create vite 用喜歡的框架搭建 Vite 項目,或者使用 vite.new 在線打開啟動模板來使用 Vite 5。還可以運行 pnpm create vite-extra 來訪問其他框架和運行時(Solid、Deno、SSR 和庫啟動器)的模板。當在“其他”選項下運行 create vite 時,也可以使用 create vite-extra 模板。
注意,Vite 入門模板旨在用作使用不同框架測試 Vite 的平臺。在構建下一個項目時,建議使用每個框架推薦的啟動器。一些框架現(xiàn)在也將 create vite 重定向到它們的啟動器(Vue 的 create-vue 和 Nuxt 3,以及 Svelte 的 SvelteKit)。
# Node.js 支持
Vite 不再支持已 EOL 的 Node.js 14 / 16 / 17 / 19。現(xiàn)在需要 Node.js 18 / 20+。
# 性能
除了 Rollup 4 的構建性能改進之外,還有一個新指南可幫助你識別和修復常見性能問題:https://vitejs.dev/guide/performance。
Vite 5 還引入了 server.warmup,這是一項改善啟動時間的新功能。它允許定義應在服務器啟動后立即進行預轉換的模塊列表。當使用 --open 或 server.open 時,Vite 還會自動預熱應用的入口點或提供的 URL 以打開。
# 主要更新
Vite 現(xiàn)在由 Rollup 4 提供支持
Vite 現(xiàn)在使用 Rollup 4,它也帶來了重大變化,包括:
- Import assertions 已更名為 import attributes。
- 不再支持 Acorn 插件。
- 對于 Vite 插件,this.resolve的skipSelf選項現(xiàn)在默認為true。
- 對于 Vite 插件,this.parse目前僅支持allowReturnOutsideFunction選項。
CJS Node API 已被棄用
Vite的CJS Node API 已被棄用。當調(diào)用require('vite')時,現(xiàn)在會記錄棄用警告。應該更新文件或框架,以導入Vite的ESM構建而不是CJS構建。
在基本的Vite項目中,請確保:
- vite.config.js文件內(nèi)容使用ESM語法。
- 最接近的package.json文件包含"type": "module",或者使用.mjs擴展名,例如vite.config.mjs。
對于其他項目,有一些常見的方法:
- 將 ESM 配置為默認選項,根據(jù)需要選擇 CJS:在項目的package.json中添加"type": "module"。所有*.js文件現(xiàn)在都被解釋為ESM,并且需要使用 ESM 語法??梢詫в?cjs擴展名的文件重命名,以繼續(xù)使用 CJS。
- 將 CJS 配置為默認選項,根據(jù)需要選擇ESM:如果項目的package.json沒有"type": "module",所有*.js文件都將被解釋為 CJS??梢詫в?mjs擴展名的文件重命名,以使用 ESM。
- 動態(tài)導入 Vite:如果需要繼續(xù)使用 CJS,可以使用import('vite')進行動態(tài)導入 Vite。這需要代碼以異步上下文編寫,但由于 Vite 的 API 大多是異步的,因此應該仍然可以管理。
重新制定 define 和 import.meta.env.* 的替代策略
在 Vite 4 中,define和import.meta.env.*功能在開發(fā)和構建中使用不同的替換策略:
- 在開發(fā)環(huán)境中,這兩個功能被注入為全局變量到globalThis和import.meta中。
- 在構建環(huán)境中,這兩個功能被靜態(tài)地使用正則表達式替換。
這導致在嘗試訪問這些變量時出現(xiàn)開發(fā)環(huán)境和構建環(huán)境的不一致性,有時甚至會導致構建失敗。例如:
// 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 來處理構建中的替換,與開發(fā)行為保持一致。
這個改變不應該影響大多數(shù)設置,因為已經(jīng)有文檔說明define的值應該遵循 esbuild 的語法:
為了與 esbuild 的行為保持一致,表達式必須是一個 JSON 對象(null、boolean、number、string、array或object)或者一個單個的標識符。
然而,如果你更喜歡直接保持靜態(tài)替換值,可以使用 @rollup/plugin-replace[1]。
worker.plugins 現(xiàn)在是一個函數(shù)
在 Vite 4 中,worker.plugins接受一個插件數(shù)組((Plugin | Plugin[])[])。而在 Vite 5 中,它需要配置為一個返回插件數(shù)組的函數(shù)(() => (Plugin | Plugin[])[])。這個改變是為了使并行的工作器構建更加一致和可預測。
允許包含 .
的路徑回退到 index.html
在 Vite 4 中,在開發(fā)環(huán)境中訪問包含點"."的路徑時,即使將appType設置為'spa'(默認值),也不會回退到index.html。而在 Vite 5 中,它將會回退到index.html。
注意,如果將圖像路徑指向一個不存在的文件(例如<img src="./file-does-not-exist.png">),瀏覽器將不再在控制臺中顯示 404 錯誤消息。
統(tǒng)一開發(fā)和預覽 HTML 服務行為
在 Vite 4 中,開發(fā)服務器和預覽服務器根據(jù)目錄結構和末尾斜杠來不同地提供HTML服務。這會導致在測試構建后的應用時出現(xiàn)不一致性。Vite 5 將重構成以下類似的單一行為,假設以下文件結構:
├── index.html
├── file.html
└── dir
└── index.html
manifest 文件會在 .vite 目錄中生成
默認情況下,Vite 4 中的清單文件(build.manifest和build.ssrManifest)是在構建的根目錄中生成的。
而從 Vite 5 開始,默認情況下它們將會生成在.build.outDir目錄中的.vite目錄中。這個改變有助于避免公共文件與相同的清單文件名在復制到build.outDir時發(fā)生沖突。
CLI 快捷方式需要額外的 Enter 鍵觸發(fā)
現(xiàn)在,CLI的快捷方式(例如r鍵重啟開發(fā)服務器)需要額外按下Enter鍵才能觸發(fā)快捷方式。例如,按下r鍵后再按Enter鍵來重啟開發(fā)服務器。
這個改變防止 Vite 吞噬和控制特定于操作系統(tǒng)的快捷方式,使得將 Vite 開發(fā)服務器與其他進程結合使用時更加兼容。
更新experimentalDecorators和useDefineForClassFields在 TypeScript 中的行為
Vite 5 使用 esbuild 0.19,并移除了對 esbuild 0.18 的兼容層,這改變了 experimentalDecorators 和 useDefineForClassFields 的處理方式。
- experimentalDecorators默認情況下是未啟用的,需要在tsconfig.json中將compilerOptions.experimentalDecorators設置為true才能使用裝飾器。
- useDefineForClassFields的默認值取決于TypeScript的目標值,如果目標不是ESNext或ES2022或更新版本,或者沒有tsconfig.json文件,則useDefineForClassFields將默認為false,這可能會導致問題,因為默認的esbuild.target值是 esnext。它可能會轉譯為靜態(tài)初始化塊,而這在瀏覽器中可能不被支持。
因此,建議在配置tsconfig.json時將目標設置為ESNext或ES2022或更新版本,或者顯式將useDefineForClassFields設置為true。
{
"compilerOptions": {
// 如果使用裝飾器,設置為true
"experimentalDecorators": true,
// 如果在瀏覽器中看到解析錯誤,設置為true
"useDefineForClassFields": true
}
}
移除--https標志和https: true
-https標志在內(nèi)部設置了server.https: true和preview.https: true。這個配置原本是用來與 Vite 3 中取消的自動 https 證書生成功能一起使用的。因此,這個配置不再有用,因為它會啟動一個沒有證書的 Vite HTTPS 服務器。
如果使用的是@vitejs/plugin-basic-ssl或vite-plugin-mkcert,它們已經(jīng)在內(nèi)部設置了 https 配置,所以可以在設置中移除--https、server.https: true和preview.https: true。
移除resolvePackageEntry和resolvePackageData API
resolvePackageEntry和resolvePackageData API已被移除,因為它們暴露了 Vite 的內(nèi)部結構,并阻礙了過去 Vite 4.3 的潛在優(yōu)化??梢允褂玫谌桨娲@些API,例如:
- resolvePackageEntry: 使用 import.meta.resolve[2] 或 import-meta-resolve[3]包。
- resolvePackageData: 同上,并向上遍歷包目錄以獲取根package.json?;蛘呤褂蒙鐓^(qū)的 vitefu[4] 包。
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查詢參數(shù)代替
- import.meta.globEager:改用 import.meta.glob('*', { eager: true }) 代替 ssr.format:'cjs' 和 legacy.buildSsrCjsExternalHeuristics
- server.middlewareMode:'ssr' 和 server.middlewareMode:'html':改用 appType + server.middlewareMode: true 代替。
[1]@rollup/plugin-replace: https://github.com/rollup/plugins/tree/master/packages/replace。
[2]import.meta.resolve]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta/resolve。
[3]import-meta-resolve: https://github.com/wooorm/import-meta-resolve。
[4]vitefu: https://github.com/svitejs/vitefu。