昨天追到 pre-bundling 的入口 createDepsOptimizer
裡的 init
有三個關鍵函式,今天繼續來往下追,在開始前先複習一下簡化過的入口邏輯結構:
這裡先將以上的邏輯整理成下面這張圖更清楚:
解析 loadCachedDepOptimizationMetadata
這個函式如程式碼中註解,這段基本上就是文件上關於檔案系統快取的實現,最後返回 pre-bundle 過的快取資料:
當快取資料不存在時,會繼續進到 discoverProjectDependencies
這個函式來掃描專案中有用到哪些依賴套件:
而其中看起來真正做事的會是 scanImports
這個函式,再往裡面追的話可以看到:
原本以為實際上用到 esbuild 來執行 pre-bundle 的地方應該會是在更後面的 runOptimizeDeps
裡,不是看很懂為什麼這邊會用 esbuild 來做 rebuild,是真的有打包出什麼內容嗎?
再繼續往 prepareEsbuildScanner
這個地方追進去會發現一個關鍵點:
看到這裡在初始化 esbuild 設定檔的地方應該是關鍵,於是好奇查了下 esbuild 的文件找到關於這個 write
的意思:
The build API call can either write to the file system directly or return the files that would have been written as in-memory buffers
翻成白話文的話應該是說這個 write 的設定會決定 build API 如何輸出打包後的內容,如果設定成 false
的話就會有點類似 dry run 的方式把結果寫進記憶體緩衝區中。所以可以整理一下這兩處使用 esbuild 情境的差異:
scanImports
:利用 esbuild 去做 dry run,快速識別專案中的套件依賴關係runOptimizeDeps
:利用 esbuild 實際執行 pre-bundling
先劇透下如果往 runOptimizeDeps
裡面追進去會看到其中有一段 prepareEsbuildOptimizerRun
在準備 esbuild 設定 (ref),其中就沒有用到 write
這個屬性,因此會真的去打包出東西來。
今天重新釐清了一下從 pre-bundling 進入點的綜觀邏輯,並一路追到其中在掃描整個專案中套件依賴的原理,比較有趣的是找到 esbuild 其中有一個 write
設定可以拿來控制類似你這次的行為是想要掃描檔案還是要做打包,算是跟 esbuild 文件有了第一次的交集,明天會繼續把剩下的 runOptimizeDeps
追完,再做個總整理。
另外也試著利用 Excalidraw 把目前追原始碼的地圖給整理了出來:
實際用了這工具後,也發現裡面還有 beta 版 AI 功能,可以用 prompt 可能像是程式碼、條列筆記等,請它快速初始化流程圖草稿,不用真的從頭拉起方便許多,雖然免費版每天有次數限制就是了,也推薦給大家: