當(dāng)你首次啟動(dòng) vite
時(shí),你可能會(huì)注意到打印出了以下信息:
Optimizable dependencies detected: (偵測(cè)到可優(yōu)化的依賴:)
react, react-dom
Pre-bundling them to speed up dev server page load...(將預(yù)構(gòu)建它們以提升開(kāi)發(fā)服務(wù)器頁(yè)面加載速度)
(this will be run only when your dependencies have changed)(這將只會(huì)在你的依賴發(fā)生變化時(shí)執(zhí)行)
這就是 Vite 執(zhí)行的所謂的“依賴預(yù)構(gòu)建”。這個(gè)過(guò)程有兩個(gè)目的:
1、CommonJS 和 UMD 兼容性: 開(kāi)發(fā)階段中,Vite 的開(kāi)發(fā)服務(wù)器將所有代碼視為原生 ES 模塊。因此,Vite 必須先將作為 CommonJS 或 UMD 發(fā)布的依賴項(xiàng)轉(zhuǎn)換為 ESM。
當(dāng)轉(zhuǎn)換 CommonJS 依賴時(shí),Vite 會(huì)執(zhí)行智能導(dǎo)入分析,這樣即使導(dǎo)出是動(dòng)態(tài)分配的(如 React),按名導(dǎo)入也會(huì)符合預(yù)期效果:
// 符合預(yù)期
import React, { useState } from 'react'
2、性能: Vite 將有許多內(nèi)部模塊的 ESM 依賴關(guān)系轉(zhuǎn)換為單個(gè)模塊,以提高后續(xù)頁(yè)面加載性能。
一些包將它們的 ES 模塊構(gòu)建作為許多單獨(dú)的文件相互導(dǎo)入。例如,??lodash-es
?? 有超過(guò) 600 個(gè)內(nèi)置模塊!當(dāng)我們執(zhí)行 ?import { debounce } from 'lodash-es'
? 時(shí),瀏覽器同時(shí)發(fā)出 600 多個(gè) HTTP 請(qǐng)求!盡管服務(wù)器在處理這些請(qǐng)求時(shí)沒(méi)有問(wèn)題,但大量的請(qǐng)求會(huì)在瀏覽器端造成網(wǎng)絡(luò)擁塞,導(dǎo)致頁(yè)面的加載速度相當(dāng)慢。
通過(guò)預(yù)構(gòu)建 ?lodash-es
? 成為一個(gè)模塊,我們就只需要一個(gè) HTTP 請(qǐng)求了!
如果沒(méi)有找到相應(yīng)的緩存,Vite 將抓取你的源碼,并自動(dòng)尋找引入的依賴項(xiàng)(即 "bare import",表示期望從node_modules
解析),并將這些依賴項(xiàng)作為預(yù)構(gòu)建包的入口點(diǎn)。預(yù)構(gòu)建通過(guò) ?esbuild
?執(zhí)行,所以它通常非常快。
在服務(wù)器已經(jīng)啟動(dòng)之后,如果遇到一個(gè)新的依賴關(guān)系導(dǎo)入,而這個(gè)依賴關(guān)系還沒(méi)有在緩存中,Vite 將重新運(yùn)行依賴構(gòu)建進(jìn)程并重新加載頁(yè)面。
在一個(gè) monorepo 啟動(dòng)中,該倉(cāng)庫(kù)中的某個(gè)依賴可能會(huì)成為另一個(gè)包的依賴。Vite 會(huì)自動(dòng)偵測(cè)沒(méi)有從 node_modules
解析的依賴項(xiàng),并將鏈接的依賴視為源碼。它不會(huì)嘗試打包被鏈接的依賴,而是會(huì)分析被鏈接依賴的依賴列表。
Note
由于依賴關(guān)系的處理方式不同,鏈接的依賴關(guān)系在最終構(gòu)建時(shí)可能無(wú)法正常工作。 使用 ?npm package
? 代替所有本地依賴,以避免最終的 bundle 問(wèn)題。
默認(rèn)的依賴項(xiàng)發(fā)現(xiàn)為啟發(fā)式可能并不總是可取的。在你想要顯式地從列表中包含/排除依賴項(xiàng)的情況下, 請(qǐng)使用 ?optimizeDeps
? 配置項(xiàng)。
當(dāng)你遇到不能直接在源碼中發(fā)現(xiàn)的 import 時(shí),?optimizeDeps.include
? 或 ?optimizeDeps.exclude
? 就是典型的用例。例如,import 可能是插件轉(zhuǎn)換的結(jié)果。這意味著 Vite 無(wú)法在初始掃描時(shí)發(fā)現(xiàn) import —— 它只能在瀏覽器請(qǐng)求文件時(shí)轉(zhuǎn)換后才能發(fā)現(xiàn)。這將導(dǎo)致服務(wù)器在啟動(dòng)后立即重新打包。
?include
?和 ?exclude
?都可以用來(lái)處理這個(gè)問(wèn)題。如果依賴項(xiàng)很大(包含很多內(nèi)部模塊)或者是 CommonJS,那么你應(yīng)該包含它;如果依賴項(xiàng)很小,并且已經(jīng)是有效的 ESM,則可以排除它,讓瀏覽器直接加載它。
Vite 會(huì)將預(yù)構(gòu)建的依賴緩存到 ?node_modules/.vite
?。它根據(jù)幾個(gè)源來(lái)決定是否需要重新運(yùn)行預(yù)構(gòu)建步驟:
package.json
? 中的 ?dependencies
?列表package-lock.json
?, ?yarn.lock
?,或者 ?pnpm-lock.yaml
?vite.config.js
? 相關(guān)字段中配置過(guò)的只有在上述其中一項(xiàng)發(fā)生更改時(shí),才需要重新運(yùn)行預(yù)構(gòu)建。
如果出于某些原因,你想要強(qiáng)制 Vite 重新構(gòu)建依賴,你可以用 ?--force
? 命令行選項(xiàng)啟動(dòng)開(kāi)發(fā)服務(wù)器,或者手動(dòng)刪除 ?node_modules/.vite
? 目錄。
解析后的依賴請(qǐng)求會(huì)以 HTTP 頭 ?max-age=31536000,immutable
? 強(qiáng)緩存,以提高在開(kāi)發(fā)時(shí)的頁(yè)面重載性能。一旦被緩存,這些請(qǐng)求將永遠(yuǎn)不會(huì)再到達(dá)開(kāi)發(fā)服務(wù)器。如果安裝了不同的版本(這反映在包管理器的 lockfile 中),則附加的版本 query 會(huì)自動(dòng)使它們失效。如果你想通過(guò)本地編輯來(lái)調(diào)試依賴項(xiàng),你可以:
--force
? 命令以重新構(gòu)建依賴;
更多建議: