跳轉到內容

效能

雖然 Vite 預設情況下速度很快,但隨著專案需求的增長,效能問題可能會逐漸顯現。本指南旨在幫助你識別並修復常見的效能問題,例如:

  • 伺服器啟動緩慢
  • 頁面載入緩慢
  • 構建緩慢

檢查瀏覽器設定

某些瀏覽器擴充套件可能會干擾請求,降低大型應用的啟動和過載速度,尤其是在使用瀏覽器開發者工具時。在這種情況下,我們建議建立一個不帶擴充套件程式的專用開發配置檔案,或者切換到隱身模式使用 Vite 開發伺服器。隱身模式通常比不帶擴充套件的常規配置更快。

Vite 開發伺服器會對預打包的依賴項進行強快取,併為原始碼實現快速的 304 響應。在瀏覽器開發者工具開啟的情況下停用快取,會對啟動和全頁面過載時間產生很大影響。請確保在處理 Vite 伺服器時未啟用“停用快取(Disable Cache)”。

審查配置的 Vite 外掛

Vite 的內建外掛和官方外掛經過最佳化,在保證與更廣泛生態系統的相容性的同時,儘可能減少不必要的工作。例如,程式碼轉換在開發階段使用正則表示式,但在構建階段會進行完整的解析以確保準確性。

然而,社群外掛的效能不在 Vite 的控制範圍內,這可能會影響開發體驗。在使用額外的 Vite 外掛時,你可以關注以下幾點:

  1. 僅在特定情況下使用的重型依賴項應進行動態匯入,以減少 Node.js 的啟動時間。重構示例:vite-plugin-react#212vite-plugin-pwa#224

  2. buildStartconfigconfigResolved 鉤子不應執行冗長且耗時的操作。這些鉤子在開發伺服器啟動期間被等待(awaited),這會延遲你在瀏覽器中訪問站點的時間。

  3. resolveIdloadtransform 鉤子可能會導致某些檔案載入比其他檔案慢。雖然有時不可避免,但仍值得檢查是否存在可最佳化的地方。例如,在進行完整轉換之前,檢查 code 是否包含特定關鍵字,或 id 是否匹配特定副檔名。

    轉換檔案所需的時間越長,在瀏覽器中載入站點時請求瀑布流(request waterfall)就會越明顯。

    你可以使用 vite --debug plugin-transformvite-plugin-inspect 來檢查轉換檔案的時長。請注意,由於非同步操作往往會導致計時不準確,你應該將這些數字視為粗略估計,但它仍然可以揭示代價高昂的操作。

效能分析 (Profiling)

你可以執行 vite --profile,訪問站點,並在終端輸入 p + enter 來記錄 .cpuprofile。然後可以使用像 speedscope 這樣的工具來檢查效能配置檔案並識別瓶頸。你還可以分享這些配置檔案給 Vite 團隊,以幫助我們找出效能問題。

減少解析操作

當頻繁觸發最壞情況時,解析匯入路徑可能是一項代價高昂的操作。例如,Vite 支援透過 resolve.extensions 選項來“猜測”匯入路徑,預設值為 ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json']

當你嘗試使用 import './Component' 匯入 ./Component.jsx 時,Vite 將執行以下步驟來解析它:

  1. 檢查 ./Component 是否存在,否。
  2. 檢查 ./Component.mjs 是否存在,否。
  3. 檢查 ./Component.js 是否存在,否。
  4. 檢查 ./Component.mts 是否存在,否。
  5. 檢查 ./Component.ts 是否存在,否。
  6. 檢查 ./Component.jsx 是否存在,是!

如上所示,解析一個匯入路徑總共需要 6 次檔案系統檢查。隱式匯入越多,解析路徑所積累的時間就越多。

因此,顯式宣告匯入路徑通常更好,例如 import './Component.jsx'。你也可以縮減 resolve.extensions 的列表以減少一般的檔案系統檢查,但必須確保它對 node_modules 中的檔案也有效。

如果你是外掛作者,請確保僅在需要時才呼叫 this.resolve,以減少上述檢查次數。

TypeScript

如果你正在使用 TypeScript,請在 tsconfig.jsoncompilerOptions 中啟用 "moduleResolution": "bundler""allowImportingTsExtensions": true,以便在程式碼中直接使用 .ts.tsx 副檔名。

避免使用 Barrel 檔案

Barrel 檔案是指那些重新匯出同一目錄下其他檔案 API 的檔案。例如:

src/utils/index.js
js
export * from './color.js'
export * from './dom.js'
export * from './slash.js'

當你只匯入單個 API 時,例如 import { slash } from './utils',該 barrel 檔案中的所有檔案都需要被獲取並轉換,因為它們可能包含 slash API,也可能包含在初始化時執行的副作用。這意味著在初始頁面載入時,你載入的檔案比實際需要的多,從而導致頁面載入變慢。

如果可能,你應該避免使用 barrel 檔案,並直接匯入單個 API,例如 import { slash } from './utils/slash.js'。你可以閱讀 issue #8237 獲取更多資訊。

預熱頻繁使用的檔案

Vite 開發伺服器僅在瀏覽器請求時才轉換檔案,這使得它能夠快速啟動,並僅對已使用的檔案應用轉換。它也可以在預見到某些檔案即將被請求時進行預轉換。然而,如果某些檔案轉換時間較長,仍可能會出現請求瀑布流。例如:

假設一個匯入圖,左側檔案匯入右側檔案:

main.js -> BigComponent.vue -> big-utils.js -> large-data.json

只有在檔案被轉換後,才能確定匯入關係。如果 BigComponent.vue 需要一些時間來轉換,big-utils.js 就必須等待輪到它,依此類推。即使內建了預轉換,這也會導致內部瀑布流。

Vite 允許你使用 server.warmup 選項預熱你所知道的頻繁使用的檔案(例如 big-utils.js)。這樣,當 big-utils.js 被請求時,它就已經準備好並被快取,從而可以立即提供服務。

你可以透過執行 vite --debug transform 並檢查日誌來查詢頻繁使用的檔案。

bash
vite:transform 28.72ms /@vite/client +1ms
vite:transform 62.95ms /src/components/BigComponent.vue +1ms
vite:transform 102.54ms /src/utils/big-utils.js +1ms
vite.config.js
js
export default defineConfig({
  server: {
    warmup: {
      clientFiles: [
        './src/components/BigComponent.vue',
        './src/utils/big-utils.js',
      ],
    },
  },
})

注意:你應僅預熱頻繁使用的檔案,以免在啟動時給 Vite 開發伺服器造成過重負擔。檢視 server.warmup 選項以瞭解更多資訊。

使用 --openserver.open 也能提升效能,因為 Vite 會自動預熱應用的入口點或指定的 URL。

使用更輕量級或原生工具

保持 Vite 在程式碼庫不斷增長時依然快速的關鍵,在於減少對原始檔(JS/TS/CSS)的處理工作量。

減少工作量的例子:

  • 儘可能使用 CSS 代替 Sass/Less/Stylus(巢狀可以由 PostCSS / Lightning CSS 處理)
  • 不要將 SVG 轉換為 UI 框架元件(React, Vue 等)。直接將其作為字串或 URL 匯入。

使用原生工具的例子:

雖然 Vite 核心基於原生工具,但為了提供更好的相容性和功能集,某些功能預設仍使用非原生工具。但對於大型應用來說,切換到原生工具可能是值得的。