啟用分階段建置
預設情況下,Rush 會在每個專案資料夾中分別執行建置指令碼 (類似於 npm run build
) 來建置每個專案,並在相依性圖允許的情況下平行處理專案。從 Rush 的角度來看,在該建置指令碼中發生的所有事情都是單一操作。
「分階段建置」是一種透過將個別操作定義為可在專案上執行的「階段」來提高平行性的方法。例如,如果專案 B 相依於專案 A,我們可以先建置專案 A,然後在平行執行專案 A 的單元測試時開始建置專案 B。
注意:分階段建置建立於建置快取功能的基礎之上,並且需要該功能。如果您尚未為您的單一儲存庫啟用建置快取,請參閱啟用建置快取。
啟用實驗功能
在 common/config/rush/experiments.json
中,啟用 "phasedCommands"
實驗功能。
{
"phasedCommands": true
}
定義階段
在 common/config/rush/command-line.json
中,新增一個 "phases"
區段,如下所示
{
"phases": [
{
/**
* The name of the phase. Note that this value must start with the \"_phase:\" prefix.
*/
"name": "_phase:build",
/**
* The dependencies of this phase.
*/
"dependencies": {
"upstream": ["_phase:build"]
},
/**
* Normally Rush requires that each project's package.json has a \"scripts\" entry matching the phase name. To disable this check, set \"ignoreMissingScript\" to true.
*/
"ignoreMissingScript": true,
/**
* By default, Rush returns a nonzero exit code if errors or warnings occur during a command. If this option is set to \"true\", Rush will return a zero exit code if warnings occur during the execution of this phase.
*/
"allowWarningsOnSuccess": false
},
{
"name": "_phase:test",
"dependencies": {
"self": ["_phase:build"]
},
"ignoreMissingScript": true,
"allowWarningsOnSuccess": false
}
]
}
在此範例中,我們定義了兩個階段 -- _phase:build
和 _phase:test
。_phase:build
操作相依於其上游專案的 _phase:build
操作 (使用傳統的 Rush 相依性圖)。_phase:test
操作不相依於任何上游專案,但需要先完成其「自身」專案的 _phase:build
操作。請注意,階段名稱必須以 _phase:
開頭。
個別專案可以選擇不實作階段 (如果已啟用 ignoreMissingScript
),但它們無法定義自己的階段,或變更階段的相依性。這可確保階段在您的單一儲存庫內行為一致,無論您正在建置哪個專案子集。
重新定義建置和測試指令
在 common/config/rush/command-line.json
的 "commands"
區段中,將 "build"
指令重新定義為 phased
指令,而不是 bulk
指令,並指定您希望它執行的階段。在以下範例中,我們也定義了 "test"
指令。
{
"commands": [
{
"commandKind": "phased",
"name": "build",
"phases": ["_phase:build"],
"enableParallelism": true,
"incremental": true
},
// No need to define "rebuild", by default, it is the same as build
// but with incremental=false.
{
"commandKind": "phased",
"name": "test",
"summary": "Build and test all projects.",
"phases": ["_phase:build", "_phase:test"],
"enableParallelism": true,
"incremental": true
},
{
"commandKind": "phased",
"name": "retest",
"summary": "Build and test all projects.",
"phases": ["_phase:build", "_phase:test"],
"enableParallelism": true,
"incremental": false
}
]
}
此指令定義展示了分階段建置的另一個實用功能:我們可以建立我們的「階段」建置區塊,然後從這些區塊建立指令。我們可以定義 rush build
的意思為「建置所有專案而不執行測試」,而 rush test
的意思為「建置所有專案並執行測試」,而不是讓 rush build
為所有專案執行建置和測試。
將參數指派給階段
如果您已在 command-line.json
中為建置指令定義任何自訂參數,您現在需要將它們關聯到階段,以便 Rush 知道哪些階段可以接受您的參數。
以下是一些範例
{
"parameters": [
{
"longName": "--production",
"parameterKind": "flag",
"description": "Perform a production build, including minification and localization steps",
"associatedCommands": ["build", "rebuild", "test", "retest"],
"associatedPhases": ["_phase:build"]
},
{
"longName": "--update-snapshots",
"parameterKind": "flag",
"description": "Update unit test snapshots for all projects",
"associatedCommands": ["test", "retest"],
"associatedPhases": ["_phase:test"]
}
]
}
在這裡,我們定義了一個可在建置指令的所有 4 種變體上指定的旗標 (--production
),但它只會傳遞到「建置」階段。而且,我們定義了另一個只能在 test
和 retest
指令上指定的旗標 (--update-snapshots
),並且只會傳遞到 test
階段。
因此,如果我們要執行此指令
rush test --production --update-snapshots
Rush 會將 --production
參數傳遞到每個專案的 _phase:build
指令碼,然後將 --update-snapshots
參數傳遞到每個專案的 _phase:test
指令碼。
將階段指令碼新增至您的專案
在您單一儲存庫中每個專案的 package.json
檔案中,新增新的 _phase:
指令碼
{
"scripts": {
"_phase:build": "heft build --clean",
"_phase:test": "heft test --no-build",
"build": "heft build --clean",
"test": "heft test --clean"
}
}
上面的範例嘗試調整開發人員對 build
和 test
指令的預期
- 移至專案資料夾並執行
rushx build
會清除並建置專案,而不執行測試。 - 移至專案資料夾並執行
rushx test
會清除、建置和測試專案。 - 執行
rush build --only <project>
會清除並建置專案,而不執行測試。 - 執行
rush test --only <project>
會清除、建置和測試專案。
在可能的情況下,對於您定義的任何自訂階段,請記住此模式 -- 重要的不是階段的實作方式與 rushx 指令完全相同,而是 rush <something>
和 rushx <something>
會產生相似的結果 (如果適用)。
某些專案可能沒有任何有意義的階段工作要做,在這種情況下,您可以將其定義為空操作 (""
),或將其完全省略 (如果在階段定義中指定了 ignoreMissingScript
)。
定義每個階段的輸出資料夾名稱
在每個專案 (或最好是每個裝配設定檔) 的 rush-project.json
設定檔中,重新定義您的 operationSettings
,以便每個資料夾僅在一個階段中指定。例如
{
"operationSettings": [
// Old configuration (before phases)
{
"operationName": "build",
"outputFolderNames": ["lib", "lib-commonjs", "dist", "temp"]
},
// New configuration (after phases)
{
"operationName": "_phase:build",
"outputFolderNames": ["lib", "lib-commonjs", "dist"]
},
{
"operationName": "_phase:test",
"outputFolderNames": ["temp/coverage", "temp/jest-reports"]
}
]
}
請注意 _phase:build
和 _phase:test
指定的輸出資料夾之間沒有重疊 -- 這是分階段建置的一個重要的新要求。一般而言,如果某個操作的輸出可以被不同的操作修改,Rush 就無法可靠地快取該操作的輸出,因此您應該將操作結構化,以便如果 _phase:build
產生一個 "lib"
資料夾,則沒有其他操作會將輸出放入該資料夾。
分階段建置功能仍在開發中。歡迎提供意見!
一些相關的 GitHub 問題供您追蹤