增量建置
Rush 的增量建置功能會跳過已是最新的專案,藉此加速建置程序。在此情境中,「已是最新的」表示
- 專案已在本機建置,且
- 自上次建置以來,其輸入檔案和 NPM 相依性未變更,且
- 如果專案相依於任何其他 Rush 專案,則這些專案也必須是最新的,且
- 命令列參數未變更。(例如,在執行
rush build
後叫用rush build --production
會需要重新建置。)
根據預設,「輸入檔案」是指專案資料夾下的所有來源檔案,除了 .gitignore
排除的檔案;您可以使用 rush-project.json 設定檔自訂詳細資料。
此功能可以與專案選取參數結合使用,讓使用者明確告知 Rush 要處理哪些專案。增量建置會重複使用本機磁碟上現有的輸出。這與 Rush 的建置快取功能形成對比,後者可以從雲端儲存容器提取先前建置的輸出。
如何使用
若要查看增量建置的實際運作情況,只需執行 rush build
命令兩次
rush install
# This might take several minutes...
rush build
# ...but the second time it finishes in just a few seconds.
rush build
原生的 rush build
已預設為增量建置。(而 rush rebuild
是此命令的非增量變體。)如果您定義自己的自訂批次命令,您也可以透過在command-line.json 設定檔中啟用 "incremental"
選項,將其設定為增量建置。
其運作方式為何?
您的專案建置指令碼(由 rushx build
或 npm run build
叫用)可能已經實作其自己的增量最佳化。例如,Heft 會維護各種工作的多個快取。但是,即使 rushx build
對於專案沒有執行任何工作,仍需要非零的額外負擔,才能產生 Node.js 程序、評估 JavaScript 檔案,以及比較個別檔案的時間戳記。假設所有這些作業對於一個專案僅需要 500 毫秒。如果您的單一儲存庫有 100 個專案,則在所有項目皆為最新的情況下,這會產生 100 x 0.5 = 50 秒的計算時間。
Rush 會透過單次傳遞執行儲存庫的自身全域分析來消除此額外負擔,如此一來,對於最新的專案完全不會叫用建置指令碼。作為額外的最佳化,Rush 的增量分析會仰賴檔案雜湊而不是時間戳記。例如,如果您切換到不同的 Git 分支,然後再切換回來,許多檔案的時間戳記可能會遭到變更,但是只要來源檔案內容未變更,Rush 的增量分析就不會受到影響。檔案雜湊是由 @rushstack/package-deps-hash 程式庫管理。雜湊會儲存在類似 <您的專案>/.rush/temp/package-deps_<工作名稱>.json
的檔案中。檢查此檔案可以深入瞭解演算法的運作方式。
增量分析實際上包含三種不同的行為
不進行增量最佳化: 如果叫用的 Rush 命令不是增量的(在 command-line.json 中為
incremental: false
),則每次都會重新執行作業。輸出保留: 如果停用建置快取(在 build-cache.json 中為
"buildCacheEnabled": false
),則 Rush 會檢查自上次在同一部本機電腦上建置以來,輸入檔案是否已變更。如果沒有修改任何檔案,則 Rush 會假設專案資料夾下的輸出檔案是最新的,並且會「跳過」專案而不執行任何工作。請注意,透過手動竄改輸出檔案,很容易違反此假設。快取還原: 如果啟用建置快取(在 build-cache.json 中為
"buildCacheEnabled": true
),則 Rush 會改為查詢快取提供者,以查看此專案是否已事先建置。快取提供者可能是雲端儲存或本機磁碟快取。對於快取命中,會刪除專案的輸出檔案,並以從快取還原的檔案取代。
未來可能的改進: 在目前的實作中,啟用建置快取時,永遠不會使用輸出保留策略。換句話說,專案輸出資料夾一律會先清除,然後從快取還原檔案取代,這在磁碟上的檔案已是最新的情況下,似乎沒有效率。合併輸出保留和快取還原方法是否會更有效率?
工程上的挑戰在於,當啟用建置快取時,我們也需要寫入快取,這需要對輸出的正確性抱持高度的信心。輸出保留演算法目前不會驗證輸出檔案的雜湊或檢查是否有額外的或遺失的檔案。如果實作這類驗證,其執行時間必須快於 tarball 擷取,而 tarball 擷取已經是非常快速的作業。
僅建置已變更的專案(不安全)
假設我們的單一儲存庫有下列專案
在上述圖例中,圓圈代表本機專案,而非外部 NPM 相依性。從 D
到 C
的箭頭表示 D
相依於 C
;這表示必須先建置 C
,才能建置 D
。
假設在重新建置所有項目後,我們對專案 B
下的來源檔案進行變更。專案 C
和 D
相依於 B
,因此它們也需要建置
我們可以叫用
# This command will rebuild B, C, and D
rush build
但是,如果您知道您對 C
所做的變更不會影響其 API 合約呢?例如,您可能更新了按鈕控制項的色彩,或錯誤訊息中的一些文字。
--changed-projects-only
旗標會告知 Rush 僅建置已變更檔案的專案
我們會像這樣叫用它
# This command will rebuild B (but ignore the effects for C and D)
rush build --changed-projects-only
--changed-projects-only
是「不安全」的,因為如果下游專案實際上需要重新建置,則可能會發生錯誤。此參數會假設您比 Rush 更了解哪些項目真正需要建置,藉此節省時間。如果該假設不正確,您可以隨時執行 rush build
來回到良好的狀態。