Vite 5.0有哪些新變化?

##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項目中,需要確保:

  1. 文件vite.config.js內容使用ESM語法。
  2. 最接近的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

##擴展鏈接

新手入門-在Vue框架中嵌入前端Excel表格插件(上)

VUE 3 組件開發實戰 – 在線電子表格文檔編輯(一)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章