亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JS生態(tài)系統(tǒng)加速桶裝文件使用探索

 更新時間:2024年01月21日 11:00:34   作者:大家的林語冰?人貓神話  
這篇文章主要為大家介紹了JS?生態(tài)系統(tǒng)加速桶裝文件使用實例探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

JS 桶裝文件

長話短說:一大坨項目都塞滿了只是重新 export 其他文件的文件。這就是所謂的“桶裝文件”(barrel files),也是 JS 工具在大型項目中慢如龜速的關(guān)鍵原因之一。

本期《前端翻譯計劃》共享的是“加速 JS 生態(tài)系統(tǒng)系列博客”,包括但不限于:

  • PostCSS,SVGO 等等
  • 模塊解析
  • 使用 eslint
  • npm 腳本
  • draft-js emoji 插件
  • polyfill 暴走
  • 桶裝文件暴走
  • Tailwind CSS

本期共享的是第 7 篇博客 —— 桶裝文件暴走。

新文件 import

假設(shè)我們正在開發(fā)一個包含一大坨文件的大型項目。我們添加一個新文件來處理新功能,并將另一個目錄中的函數(shù) import 到代碼中。

import { foo } from './some/other-file'

export function myCoolCode() {
  // 假裝這是超智能代碼 :)
  const result = foo()
  return result
}

我們十分雞凍地實現(xiàn)了功能,我們運行代碼,但是發(fā)現(xiàn)這需要很久才能搞定。我們編寫的代碼一目了然,理論上應(yīng)該不會太費時。為此,我們添加了某些測量代碼,查看函數(shù)完成其任務(wù)所需的時間。

import { foo } from './some/other-file'

export function myCoolCode() {
  console.time()
  const result = foo()
  console.timeEnd()
  return result
}

我們重跑代碼,大吃一斤的是,我們插入的測量結(jié)果表明,我們的函數(shù)速度驚人。我們重復(fù)測量步驟,但這次在項目的主入口文件中插入 console.time() 語句,然后再重跑代碼。梅開二度,記錄的測量結(jié)果只是反復(fù)證明我們的代碼本身速度驚人。那為什么運行代碼卻很費時呢?

沒時間解釋了快上車。這就是桶裝文件對代碼造成的破壞性影響。

收集更多信息

目前為止,我們獲得的關(guān)鍵信息是,代碼的運行時不是 bug 所在。我們測量了函數(shù),它只是運行總時間的九牛一毛。這意味著,我們可以假設(shè),所有剩余時間耽誤在運行代碼前后。根據(jù)工具的經(jīng)驗,時間通?;ㄔ陧椖看a運行前。

我有一個大膽的想法:我們聽過某些 npm 軟件包出于性能考慮,會預(yù)打包其代碼。也許這是一種新思路?我們決定測試該理論,并訴諸 esbuild 將代碼打包到一個簡單文件中。我們故意禁用任何形式的壓縮,因為我們希望代碼盡可能還原原始源碼。

完事后,我們可以運行打包后的文件來對照實驗,我和我的小伙伴都驚呆了,這次運行比貓貓還快。出于好奇,我們測量了運行 esbuild 和一起運行打包文件的時間,并注意到,它們累加起來仍然比運行原始源碼更快。?。康降资窃趺椿厥??我們明明多了打包步驟,但運行結(jié)果卻比未打包的源碼更快?

然后我悟了:打包器的超能力是,拍平和合并模塊圖。得益于 esbuild,曾經(jīng)由數(shù)千個文件組成的內(nèi)容,被合并為有且僅有一個簡單文件。這是一個有力的證明,模塊圖的大小是源碼運行緩慢的 bug 所在。桶裝文件乃速度低下的“萬惡之源”。

剖析桶裝文件

所謂“桶裝文件”,指的是僅僅用于 export 其他文件,且本身不包含代碼的文件。在編輯器支持自動 import 之前,一大坨開發(fā)者試圖將它們必須手動編寫的 import 語句的數(shù)量保持在最低限度。

// 瞄一眼所有這些 import
import { foo } from '../foo'
import { bar } from '../bar'
import { baz } from '../baz'

這就產(chǎn)生了一種模式,其中每個文件夾都有自己的 index.js 文件,該文件通常只是從位于同一目錄中的其他文件重新 export 代碼。某種程度上,這分?jǐn)偭耸謩虞斎牍ぷ?,因為一旦這樣的文件就位,所有其他代碼只需要引用一個 import 語句。

// feature/index.js
export * from './foo'
export * from './bar'
export * from './baz'

之前顯示的 import 語句現(xiàn)在可以折疊成一行。

import { foo, bar, baz } from '../feature'

一段時間后,這種模式在整個代碼庫中蔓延,項目中的每個文件夾都有一個 index.js 文件。十分整潔,對不?對對對,才怪咧。

眾生皆有病

在類似的設(shè)置中,模塊大概率會 import 另一個桶裝文件,該文件又雙叒叕會拉入一大坨其他文件,然后 import 另一個桶裝文件,子子孫孫無窮盡也。最終,我們通常會通過 import 語句的“蜘蛛網(wǎng)” import 項目中的每個文件。項目越大,加載所有這些模塊就越久。

捫心自問:哪里快了?必須加載 30k 個文件更快,還是只加載 10 個更快?

JS 愛好者的“思想鋼印”在于,模塊只會按需加載。這大錯特錯,因為這樣做會破壞依賴全局變量或模塊執(zhí)行順序的代碼。

// a.js
globalThis.foo = 123

// b.js
console.log(globalThis.foo) // 應(yīng)該打印: 123

// index.js
import './a'
import './b'

如果引擎無法加載首個 ./a 導(dǎo)入,那么代碼會意外打印 undefined 而不是 123。

桶裝文件的性能瓶頸

當(dāng)我們考慮使用測試運行程序等工具時,情況會雪上加霜。在人氣爆棚的 Jest 測試運行器中,每個測試文件都在其子進程中執(zhí)行。實際上,這意味著,每個測試文件都從零開始構(gòu)建模塊圖,并且必須支付該成本。如果在項目中構(gòu)建模塊圖需要 6 秒,并且您只有 100 個測試文件,那么您總共會浪費 10 分鐘,重復(fù)構(gòu)建模塊圖。在此期間不會運行任何測試或其他代碼。這正是引擎需要準(zhǔn)備源碼以便運行的時候。

桶裝文件作為“性能殺手”的另一個法外之地是,任何類型的 import 周期 linting 規(guī)則。通常,linter 按逐個文件運行,這意味著,需要為每個文件支付構(gòu)建模塊圖的成本。僅此一點就會導(dǎo)致 linting 時間爆表,并且在較大的項目中可能需要幾小時,這種情況司空見慣。

為了獲得某些原始數(shù)據(jù),我生成了一個項目,其中的文件相互 import,以便更好地了解構(gòu)建模塊圖的成本。每個文件都空空如也,除了 import 語句外,沒有包含任何代碼。計時是在我的“量子計算機”上測量的。

如你所見,加載更少的模塊十分值得。讓我們將這些數(shù)字應(yīng)用到一個包含 100 個測試文件的項目,其中使用測試運行程序為每個測試文件生成一個新的子進程。我們的測試運行程序可以并行運行 4 個測試:

500 個模塊:0.15s * 100 / 4 = 3.75s 開銷

1_000 個模塊:0.31s * 100 / 4 = 7.75s 開銷

25_000 個模塊:16.81s * 100 / 4 = ~7:00m 開銷

50_000 個模塊:48.44s * 100 / 4 = ~20:00m 開銷

由于這是一個綜合設(shè)置,因此這些數(shù)字都是低估的。在實際項目中,這些數(shù)字可能更糟糕。就工具性能而言,桶裝文件并不友好。

我們該咋辦?

代碼中只有少量桶裝文件通常問題不大,但當(dāng)每個文件夾都有就會出現(xiàn)問題。不幸的是,這種災(zāi)難在 JS 行業(yè)屢見不鮮。

因此,如果大家從事的項目廣泛使用桶裝文件,那么可以免費優(yōu)化:清空所有桶裝文件,使一大坨任務(wù)速度加快 60-80%。

免責(zé)聲明

本文屬于是語冰的直男翻譯了屬于是,略有刪改,僅供粉絲參考,英文原味版請傳送 Speeding up the JavaScript ecosystem - The barrel file debacle[1]。

以上就是JS 生態(tài)系統(tǒng)加速桶裝文件使用探索的詳細(xì)內(nèi)容,更多關(guān)于JS 桶裝文件的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論