與 Rush 搭配使用
「Hello World」教學課程示範如何在獨立專案中使用 Heft。現在讓我們來看看 Heft 在 Rush mono repo 中如何運作。
Heft 如何被呼叫
如果你不熟悉 Rush,「維護人員教學課程」會說明設定新 repo 的基本概念。當 Rush 在 Rush 專案資料夾中呼叫 「build
」 腳本時,Heft 就會介入接手。在我們從教學課程中的範例專案來看,這個腳本看起來像這樣
<專案資料夾>/package.json
{
. . .
"scripts": {
"build": "heft build --clean",
"start": "node lib/start.js"
}
. . .
}
使用索具套件來共用配置
mono repo 的其中一個重點主題是將「樣板」檔案減到最少。換句話說,就是將檔案和設定整併起來,這樣就不會將這些檔案和設定複製並貼到 mono repo 的每一個專案資料夾中。樣板檔案很讓人困擾,因為難以保持它們同步。若需要修正時,如果你有上百個專案,你就需要重複套用相同的修正上百次(更糟的是,如果工程師被允許自行修改其專案,你可能需要套用上百個不同的修正,維護成本非常高)。
同時,我們希望尊重 Rush 的專案隔離原則:每個專案應獨立組建,而且不應與其他專案糾纏在一起(例如透過使用相對路徑,如 ../../other-project
,參照檔案)。這樣會比較方便使用 Rush 功能,例如子集組建和增量組建。這也會讓移動 Rush 專案資料夾、在 mono repo 之間遷移專案,甚至在改變心意後停止使用 Rush 變得非常容易。基於這個原因,我們勸阻將集中式的 .eslintrc.js 檔案放在 mono repo 的根目錄,以及針對所有專案全域呼叫 ESLint 這些做法。
結合這些目標,Heft 支持稱為rig 套件的形式化設定,其中共用設定由 NPM 套件提供,而此套件會新增至每個專案的 devDependencies
。Rig 套件提供三種不同的方式來減少重複
- 設定檔可以使用
"extends"
等設定來繼承 rig 的共用設定。範例:tsconfig.json - 可完全移除可調整 rig 設定檔,使用 config/rig.json 檔案指示 Heft 在 rig 套件中找到它們。範例:config/heft.json
- Rig 套件可提供可調整的相依性,避免需要將它們新增至專案的
devDependencies
。範例:typescript 套件
使用 rig 套件 文章詳細說明這一點。
增量建置
與 Heft 搭配使用 Rush 的另一個好處是支援增量建置。例如,如果你執行 rush build
兩次,由於所有專案都已建置完成,第二次會立即完成。有趣的是,這個增量建置分析是由 Rush 本身執行,而非 Heft。
由於 JavaScript 是詮譯語言,因此每次在專案資料夾中啟動 Node.js 程序時,都會產生一些額外負擔。因此,即使 Heft 沒有執行任何工作,也可能需要 1 秒鐘來啟動工具鏈、分析輸入檔案,並確定所有內容都是最新的。對於擁有 500 個專案的單一儲存庫,這會增加 500 秒的分析時間。Rush 會透過對所有專案執行整體分析,將原始程式碼檔案的雜湊值與輸出檔案的雜湊值進行比較,來避免這個問題。如果這些雜湊值相同,則 Rush 可以確定專案完全可以略過,甚至不需要啟動 Heft。Rush 的增量建置分析適用於任何良好的指令碼,不只適用於 Heft。
使用 Heft 階段來實作 Rush 階段
使用 Rush 階段,可以更細緻地建構 Rush 的增量建置。Heft 階段特別設計為與此模型保持一致。
以下是取自 GitHub 上的 Rush 堆疊 monorepo 中 node-core-library/package.json 的摘要
"scripts": {
"build": "heft build --clean",
"test": "heft test --clean",
"_phase:build": "heft run --only build -- --clean",
"_phase:test": "heft run --only test -- --clean"
},
"test"
指令會呼叫 heft test
,這會執行 build
和 test
階段,而 "_phase:test"
指令則只會執行 test
階段。之所以會這樣運作,是因為 config/rush/command-line.json 會建置階段相依性,因此 Rush 本身會確保在執行 test
之前已經執行 build
階段。透過將這些詳細資料公開給 Rush,Heft 的階段可以使用 Rush 的建置快取來最佳化,甚至可以透過 Cobuild 功能參與分散式建置。