最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

JS 桶裝文件

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

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

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

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

新文件 import

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

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

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

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

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

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

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

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

收集更多信息

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

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

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

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

剖析桶裝文件

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

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

這就產(chǎn)生了一種模式,其中每個(gè)文件夾都有自己的 index.js 文件,該文件通常只是從位于同一目錄中的其他文件重新 export 代碼。某種程度上,這分?jǐn)偭耸謩?dòng)輸入工作,因?yàn)橐坏┻@樣的文件就位,所有其他代碼只需要引用一個(gè) import 語句。

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

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

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

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

眾生皆有病

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

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

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

// a.js
globalThis.foo = 123

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

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

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

桶裝文件的性能瓶頸

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

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

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

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

500 個(gè)模塊:0.15s * 100 / 4 = 3.75s 開銷

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

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

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

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

我們該咋辦?

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

因此,如果大家從事的項(xiàng)目廣泛使用桶裝文件,那么可以免費(fèi)優(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)文章

最新評論

陇西县| 农安县| 桑植县| 桐乡市| 湟源县| 安达市| 民县| 喜德县| 洞头县| 垦利县| 武宣县| 临潭县| 花莲县| 固原市| 延长县| 新竹县| 南郑县| 罗甸县| 红原县| 公安县| 达尔| 南安市| 盐山县| 那坡县| 古田县| 秦皇岛市| 洮南市| 清远市| 新巴尔虎右旗| 巴彦淖尔市| 连州市| 潜山县| 高台县| 益阳市| 营山县| 辽源市| 临汾市| 唐河县| 肃宁县| 通河县| 大姚县|