使用監看模式
諸如 Webpack 和 Jest 之類的常用工具,都提供「監看模式」功能:在工作完成後,工具會進入迴圈,監看檔案系統中原始程式碼檔案的變更。每當偵測到變更時,工作就會再次執行以更新其輸出。這可加速開發,因為 (1) 每當您儲存檔案時,就會自動重建,以及 (2) 工作可從記憶體內快取獲益,因為其程序永遠不會終止。
但這些功能通常只適用於單一專案。在單一儲存庫中工作時,我們需要能夠**一次監看多個專案**的監看模式。
一個思考實驗
假設我們的單一儲存庫有下列專案
在上圖中,圓圈代表本機專案,而非外部 NPM 相依性。從 D
到 C
的箭頭表示 D
相依於 C
;這表示 C
必須先建置,才能建置 D
。
假設您儲存對專案 B
的變更
對於多專案「監看模式」,我們會預期依序發生以下情況
B
應該會重建,因為其檔案已變更;- 接著,
C
應該會重建,因為它相依於B
- 接著,
D
應該會重建,因為它相依於C
- 最後,Webpack 開發伺服器 (假設由
D
主機) 會使用重建的應用程式重新整理您的網頁瀏覽器
如何使用 Rush 完成?假設我們的專案 B
和 C
有如下的簡單建置指令碼
package.json
. . .
"scripts": {
"build": "rm -Rf lib/ && tsc && jest"
}
. . .
我們可能會嘗試一個實驗,例如在無止盡的迴圈中叫用 rush build --to-except D
...
# Build everything that D depends on (but not D itself),
# and keep doing that in an endless loop:
while true; do rush build --to-except D; done
...然後,在執行此動作時,我們會在專案 D
的資料夾中叫用 heft start
(或 webpack serve
)。
您會發現此方法有一些問題
rm -Rf lib/
會刪除符號連結目標的檔案。符號連結似乎會混淆 Webpack 的檔案監看程式,因此您可能會看到許多錯誤,指出找不到匯入的檔案。Webpack 不會從中復原,因為當檔案稍後被重寫時,符號連結時間戳記不會更新。在監看時,
jest
和rm -Rf
步驟通常不重要。開發人員的**編輯 -> 重建 -> 重新載入**內部迴圈比它需要的速度慢得多。
這些問題可以藉由為監看模式建立特殊的簡化指令碼來解決,如下所示
package.json
. . .
"scripts": {
"build": "rm -Rf lib/ && tsc && jest",
"build:watch": "tsc"
}
. . .
「watchForChanges」設定 (實驗性)
Rush 的多專案「監看模式」正式化了這個基本概念,以最佳化的 chokidar 檔案系統監視器取代了簡單迴圈。
如何啟用 Rush 多專案監看模式,取決於您是否對建置指令碼使用批次指令或分階段指令。我們建議您在啟用監看模式之前切換到分階段建置,因為它對於開發人員而言是更好且更容易理解的體驗。
分階段指令的監看模式
在您的 command-line.json 設定檔中,將新的
watchOptions
區段新增至您想要啟用的每個分階段指令。例如. . .
"commands": [
{
"commandKind": "phased",
"name": "build",
"phases": ["_phase:build"],
"enableParallelism": true,
"incremental": true,
"watchOptions": {
"alwaysWatch": false,
"watchPhases": ["_phase:build"]
}
},
{
"commandKind": "phased",
"name": "test",
"phases": ["_phase:build", "_phase:test"],
"enableParallelism": true,
"incremental": true,
"watchOptions": {
"alwaysWatch": false,
"watchPhases": ["_phase:build", "_phase:test"]
}
}
]Rush 會自動將新的布林旗標
--watch
新增至具有watchOptions
屬性的任何指令。使用專案選取參數叫用指令,以選取
D
的所有相依性,但不選取D
本身# Build everything that D depends on (but not D itself),
# and keep doing that in an endless loop:
$ rush build --watch --to-except D然後,在應用程式資料夾中啟動您的開發伺服器
# Start Webpack's dev server in the folder for project D
# (which is the web application in this example):
$ cd apps/D
$ heft start # <-- or your own "npm run start" equivalent here
批次指令的監看模式
在您的 command-line.json 設定檔中新增自訂指令。繼續上述範例,我們的自訂指令會稱為
"build:watch"
。重要的設定是"incremental"
和"watchForChanges"
common/config/rush/command-line.json
. . .
"commands": [
{
"name": "build:watch",
"commandKind": "bulk",
"summary": "Build projects and watch for changes",
"description": "For details, see the article \"Using watch mode\" on the Rush website: https://rush.dev.org.tw/",
// use incremental build logic (important)
"incremental": true,
"enableParallelism": true,
// Enable "watch mode"
"watchForChanges": true
},
. . .將
"build:watch"
指令碼新增至每個 Rush 專案的 package.json 檔案。(PR #2298 旨在為"build:watch"
與"build"
相同的專案簡化此步驟。最終也可以將這些定義合併在共用的 rig 套件中。)如果您使用 Heft,您的指令碼看起來會像這樣
package.json
. . .
"scripts": {
"build": "heft build --clean",
"build:watch": "heft build"
}
. . .使用專案選取參數叫用指令,以選取
D
的所有相依性,但不選取D
本身# Build everything that D depends on (but not D itself),
# and keep doing that in an endless loop:
rush build:watch --to-except D最後,在應用程式資料夾中啟動您的開發伺服器
# Start Webpack's dev server in the folder for project D
# (which is the web application in this example):
cd apps/D
heft start # <-- or your own "npm run start" equivalent here在某些情況下,
--changed-projects-only
指令可以與"watchForChanges"
結合,以實現更快的監看。<僅建置已變更的專案>一節說明了它的運作方式以及何時適用。
「實驗性」
"watchForChanges"
功能仍處於早期階段。歡迎提供意見反應!GitHub 問題 #1202 追蹤其他工作項目和 William Bernting 的原始開發計畫。
社群解決方案
Rush 社群分享了一些有趣的替代方法來解決這個問題,這些方法也很有幫助
@telia/rush-select 是一個互動式儀表板,用於監看 Rush 專案和選取要重建的專案。
rush-dev-watcher 是 Daniel Imfeld 提供的一個簡單但實用的指令碼,可執行初始建置,然後啟動多個監看程式。