<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Vite 4.3 為何性能爆表?

          共 4361字,需瀏覽 9分鐘

           ·

          2024-04-28 09:18

          大廠技術(shù)  高級前端  Node進(jìn)階

          點(diǎn)擊上方 程序員成長指北,關(guān)注公眾號

          回復(fù)1,加入高級Node交流群

          Vite 4.3 相比 Vite 4.2 取得了驚人的性能提升,下面和大家分享一下 Vite 4.3 性能大幅提升的幕后技術(shù)細(xì)節(jié),深度閱讀,全程高能。

          fs.realpathSync 的 bug

          你可能不知道,Node 中有一個(gè)冷門的 realpathSync 性能問題 —— fs.realpathSyncfs.realpathSync.native 慢了整整 70 倍。

          雖然但是,由于在 Windows 上的行為不同,Vite 4.2 只在非 Windows 系統(tǒng)上使用 fs.realpathSync.native

          為了搞定這個(gè) bug,Vite 4.3 在 Windows 上調(diào)用 fs.realpathSync.native 時(shí)添加了網(wǎng)絡(luò)驅(qū)動(dòng)驗(yàn)證。

          Vite 從未放棄 Windows,它真的......我哭死。

          JS 重構(gòu)優(yōu)化

          當(dāng)我們重構(gòu)項(xiàng)目時(shí),千萬不要忘記針對編程語言自身的優(yōu)化。

          Vite 4.3 中有若干有趣的 JS 優(yōu)化的具體例子:

          1. 將 *yield 重構(gòu)為回調(diào)函數(shù)

          Vite 使用 tsconfck 模塊來查找和解析 tsconfig 文件。tsconfck 模塊源碼通過 *yield 遍歷指定目錄。

          Generater(生成器函數(shù))的短板之一在于,它需要更多的內(nèi)存開銷來存儲其 Generator 對象,且生成器中存在一大坨生成器上下文切換運(yùn)行。

          因此,自 tsconfck 2.1.1 以來,該模塊源碼用回調(diào)函數(shù)重構(gòu)了 *yield

          2. 將 startsWith/endsWith 重構(gòu)為 === 運(yùn)算符

          Vite 4.2 使用 startsWith/endsWith 來檢查熱門 URL 中的 '/' 前綴和后綴。

          我們測評了 str.startsWith('x') 和 str[0] === 'x' 的執(zhí)行基準(zhǔn)跑分,發(fā)現(xiàn) ===startsWith 快約 20%,同時(shí) endsWith=== 慢約 60%。

          3. 避免重新創(chuàng)建正則表達(dá)式

          Vite 需要許多正則表達(dá)式來匹配字符串,其中大多數(shù)都是靜態(tài)的,所以最好只使用它們的單例。

          Vite 4.3 優(yōu)化了正則表達(dá)式,這樣就可以重復(fù)使用它們。

          4. 放棄生成自定義錯(cuò)誤

          為了更好的開發(fā)體驗(yàn),Vite 4.2 提供了若干自定義錯(cuò)誤。

          不幸的是,這些自定義錯(cuò)誤可能會導(dǎo)致額外的計(jì)算和垃圾回收,降低 Vite 的速度。

          在 Vite 4.3 中,我們不得不放棄生成某些熱門的自定義錯(cuò)誤,比如 package.json NOT_FOUND 錯(cuò)誤,取而代之的是直接拋出原始錯(cuò)誤,從而獲取更高的性能。

          更機(jī)智的解析策略

          Vite 會解析所有已接收的 URL 和路徑,從而獲取目標(biāo)模塊。

          Vite 4.2 中存在一大坨冗余的解析邏輯和非必要的模塊搜索。

          Vite 4.3 的解析邏輯更精簡和嚴(yán)格,減少了計(jì)算量和 fs 調(diào)用。

          1. 更簡單的解析

          Vite 4.2 重度依賴 resolve 模塊來解析依賴的 package.json。

          但當(dāng)我們偷看 resolve 模塊的源碼時(shí),發(fā)現(xiàn)在解析 package.json 時(shí)存在一大坨無用邏輯。

          于是 Vite 4.3 棄用了 resolve 模塊,遵循更精簡的解析邏輯:直接檢查嵌套父目錄中是否存在 package.json

          2. 更嚴(yán)格的解析

          Vite 需要調(diào)用 Node 的 fs API 來查找模塊,但 IO 成本十分昂貴。

          Vite 4.3 縮小了文件搜索范圍,并跳過搜索某些特殊路徑,盡量減少 fs 調(diào)用。

          舉個(gè)栗子:

          1. 由于 # 符號不會出現(xiàn)在 URL 中,且用戶可以控制源文件路徑中不存在 # 符號,因此 Vite 4.3 不再檢查用戶源文件中帶有 # 符號的路徑,而只在 node_modules 中搜索它們。
          2. 在 Unix 系統(tǒng)中,Vite 4.2 首先檢查根目錄內(nèi)的每個(gè)絕對路徑,對于大多數(shù)路徑而言問題不大。但如果絕對路徑以 root 開頭,那大概率會失敗。為了在 /root/root 不存在時(shí),跳過搜索 /root/root/path-to-file,Vite 4.3 會在開頭判斷 /root/root 是否作為目錄存在,并預(yù)緩存結(jié)果。
          3. 當(dāng) Vite 服務(wù)器接收到 @fs/xxx@vite/xxx 時(shí),無需再次解析這些 URL。Vite 4.3 直接返回之前緩存的結(jié)果,不再重新解析。

          3. 更準(zhǔn)確的解析

          當(dāng)文件路徑為目錄時(shí),Vite 4.2 會遞歸解析模塊,這會導(dǎo)致不必要的重復(fù)計(jì)算。

          Vite 4.3 將遞歸解析扁平化,針對不同類型的路徑對癥下藥。拍平后緩存某些 fs 調(diào)用也更容易。

          4. package

          Vite 4.3 打破了解析 node_modules 包數(shù)據(jù)的性能瓶頸。

          Vite 4.2 使用絕對文件路徑作為包數(shù)據(jù)緩存鍵。這還不夠,因?yàn)?Vite 必須在 pkg/foo/barpkg/foo/baz 中遍歷相同的目錄。

          Vite 4.3 不僅使用絕對路徑,比如 /root/node_modules/pkg/foo/bar.js/root/node_modules/pkg/foo/baz.js,還使用遍歷的目錄作為 pkg 緩存的鍵,比如/root/node_modules/pkg/foo/root/node_modules/pkg

          另一種情況是,Vite 4.2 在單個(gè)函數(shù)內(nèi)查找深度導(dǎo)入路徑的 package.json。

          舉個(gè)栗子,當(dāng) Vite 4.2 解析 a/b/c/d 這樣的文件路徑時(shí),它首先檢查根 a/package.json 是否存在。

          如果不存在,那就按 a/b/c/package.json -> a/b/package.json 的順序查找最近的 package.json。

          但事實(shí)上,查找根 package.json 和最近的 package.json 應(yīng)該分而治之,因?yàn)樗鼈冃枰煌慕馕錾舷挛摹?/span>

          Vite 4.3 將根 package.json 和最近的 package.json 的解析分而治之,這樣它們就不會混合。

          非阻塞任務(wù)優(yōu)化

          作為一種按需服務(wù),Vite 開發(fā)服務(wù)器無需備妥所有東東就能啟動(dòng)。

          1. 非阻塞 tsconfig 解析

          Vite 服務(wù)器在預(yù)打包 ts/tsx 時(shí)需要 tsconfig 的數(shù)據(jù)。

          Vite 4.2 在服務(wù)器啟動(dòng)前,會在 configResolved 插件鉤子中等待解析 tsconfig 的數(shù)據(jù)。

          一旦服務(wù)器啟動(dòng)而尚未備妥 tsconfig 的數(shù)據(jù),即使該請求稍后需要等待 tsconfig 解析,頁面請求也可以訪問服務(wù)器,

          Vite 4.3 在服務(wù)器啟動(dòng)前初始化 tsconfig 解析,但服務(wù)器不會等待它。

          解析過程在后臺運(yùn)行。一旦 ts 相關(guān)的請求進(jìn)來,它就必須等待 tsconfig 解析完成。

          2. 非阻塞文件處理

          Vite 中存在一大坨 fs 調(diào)用,其中某些是同步的。

          這些同步 fs 調(diào)用可能會阻塞主線程,所以 Vite 4.3 將其更改為異步。此外,異步函數(shù)的并行化也更容易。

          關(guān)于異步函數(shù),我們關(guān)注的一件事是,解析后可能需要釋放一大坨 Promise 對象。

          得益于更機(jī)智的解析策略,釋放 fsPromise對象的成本要低得多。

          HMR 防抖

          請考慮兩個(gè)簡單的依賴鏈 C <- B <- AD <- B <- A。

          當(dāng)編輯 A 時(shí),HMR 會將兩者從 A 傳播到 CD。這導(dǎo)致 AB 在 Vite 4.2 中更新了兩次。

          Vite 4.3 會緩存這些遍歷過的模塊,避免多次探索它們。

          這可能會對那些具有組件集裝導(dǎo)入的文件結(jié)構(gòu)產(chǎn)生重大影響。這對于 git checkout 觸發(fā)的 HMR 也有好處。

          并行化

          并行化始終是獲取更好性能的不錯(cuò)選擇。

          在 Vite 4.3 中,我們并行化了若干核心功能,包括但不限于導(dǎo)入分析、提取 deps 的導(dǎo)出、解析模塊 url 和運(yùn)行批量優(yōu)化器。

          基準(zhǔn)測試生態(tài)系統(tǒng)

          • vite-benchmark:Vite 使用此倉庫來測評每個(gè)提交的跑分,如果您正在使用 Vite 開發(fā)大型項(xiàng)目,我們很樂意測試您的倉庫,以獲得更全面的性能。
          • vite-plugin-inspect:vite-plugin-inspect 從 0.7.20 版本開始支持顯示插件的鉤子時(shí)間,并且將來會有更多的跑分圖。
          • vite-plugin-warmup:預(yù)熱您的 Vite 服務(wù)器,并提升頁面加載速度!

          最后

          Node 社群

              


          我組建了一個(gè)氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學(xué)習(xí)感興趣的話(后續(xù)有計(jì)劃也可以),我們可以一起進(jìn)行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。

             “分享、點(diǎn)贊在看” 支持一下

          瀏覽 97
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久三级电影网站 | 91蝌蚪91 | 国产激情网站 | 久久天天躁狠狠躁夜夜爽 | 中文字幕www |