快取運作方式
在執行任何任務之前,Lerna 會計算其運算雜湊。只要運算雜湊相同,執行任務的輸出也會相同。
預設情況下,運算雜湊(例如 lerna run test --scope=remixapp
)會包含
remixapp
及其依賴項目的所有來源檔案- 相關的全局設定
- 外部依存項的版本
- 使用者提供的執行時間值,例如 Node 的版本
- CLI 命令旗標
此行為是可以自訂的。舉例來說,程式碼檢查可能僅依賴專案的原始碼和全局設定。組建可以依賴已編譯函式庫的 dts 檔案,而不是它們的來源。
Lerna 計算出任務的雜湊後,它會檢查自己是否之前執行過完全相同的運算。首先,它會在本地檢查,如果找不到,而且有設定遠端快取,它會在遠端檢查。
如果 Lerna 找到該運算,Lerna 會擷取它並重播它。Lerna 會將正確的檔案放在正確的資料夾中,並顯示終端機輸出。從使用者的角度來看,指令執行的內容相同,只是速度快了很多。
如果 Lerna 找不到對應的快取雜湊,Lerna 會執行任務,並在完成後取得輸出和終端機日誌,然後將它們儲存在本地(如果已設定,也會儲存在遠端)。所有這些都會在背景執行,所以你不用擔心。
即使在理論上這相當簡單,Lerna 還是會對其進行最佳化,以改善使用者體驗。舉例來說,Lerna 會
- 擷取標準輸出和標準錯誤輸出,以確保重播的輸出看起來相同,包括在 Windows 上。
- 透過記住哪些檔案在何處重播,將 I/O 減至最少。
- 僅在處理大型任務圖形時顯示相關輸出。
- 提供應變機制來解決快取遺漏問題。以及其他許多最佳化。
隨著工作區越來越龐大,任務圖形會看起來更像這樣
所有這些最佳化對任何非瑣碎工作區都能順利使用 Lerna 至關重要。僅執行必要的工作。其餘的會原封不動,或從快取中還原。
原始碼雜湊輸入
建置/測試應用程式或函式庫的結果取決於該專案的原始程式碼以及所有其依賴(直接或間接)的函式庫原始程式碼。
預設情況下,Lerna 較為保守。執行時,舉例來說,lerna run test --scope=remixapp
,Lerna 會考慮 remixapp
目錄中的所有檔案,以及 header
和 footer
目錄中的所有檔案(remixapp
相依性)。這將導致不必要的快取遺漏。例如,我們知道變更 footer
的規範檔案不會變更上述測試指令的結果。
我們可以定義更精確的組態,如下所示
注意事項:「{projectRoot}」和「{workspaceRoot}」是由工作執行器支援的特殊語法,在執行指令時會在內部適當地插入。因此,你不應該用固定路徑取代「{projectRoot}」或「{workspaceRoot}」,因為這會降低組態的彈性。
{
"namedInputs": {
"default": ["{projectRoot}/**/*"],
"prod": ["!{projectRoot}/**/*.spec.tsx"]
},
"targetDefaults": {
"build": {
"inputs": ["prod", "^prod"]
},
"test": {
"inputs": ["default", "^prod", "{workspaceRoot}/jest.config.ts"]
}
}
}
透過這個組態,建置指令碼只會考慮 remixapp
、header
和 footer
的非測試檔案。測試指令碼將考慮受測專案的所有原始檔案和僅限其相依性的非測試檔案。測試指令碼還會考慮工作區根目錄下的 jest 組態檔案。
執行時間雜湊輸入
執行目標也可依賴執行時間值。
{
"targetDefaults": {
"build": {
"inputs": [{ "env": "MY_ENV_NAME" }, { "runtime": "node -v" }]
}
}
}
引數雜湊輸入
最後,除了原始程式碼雜湊輸入和執行時間雜湊輸入之外,Lerna 還需要考慮引數:例如,lerna run build --scope=remixapp
和 lerna run build --scope=remixapp -- --flag=true
會產生不同的結果。
請注意,只有傳遞給 npm 指令碼本身的旗標會影響運算結果。例如,從快取的角度來看,以下指令相同。
npx lerna run build --scope=remixapp
npx lerna run build --ignore=header,footer
換句話說,Lerna 不會快取開發人員在終端上鍵入的內容。
如果你建置/測試/判斷… 多個專案,每個建置都有其自己的雜湊值,並且會從快取中擷取或執行。這表示,從快取角度來看,以下指令
npx lerna run build --scope=header,footer
與以下兩個指令相同
npx lerna run build --scope=header
npx lerna run build --scope=footer
快取內容
Lerna 在處理程序層級上運作。無論用於建置/測試/判斷… 專案的工具為何,結果都會快取。
Lerna 設定掛鉤,以便在執行指令前收集 stdout/stderr。所有輸出皆快取,並在快取命中時重播。
Lerna 也會快取指令產生的檔案。檔案/資料夾清單列在專案的 package.json
中的 outputs
屬性
注意事項:「{projectRoot}」和「{workspaceRoot}」是由工作執行器支援的特殊語法,在執行指令時會在內部適當地插入。因此,你不應該用固定路徑取代「{projectRoot}」或「{workspaceRoot}」,因為這會降低組態的彈性。
{
"nx": {
"targets": {
"build": {
"outputs": ["{projectRoot}/build", "{projectRoot}/public/build"]
}
}
}
}
若專案的 package.jsojn
檔案中未定義特定目標的 outputs
屬性,Lerna 將會檢視 nx.json
的 targetDefaults
區段
{
...
"targetDefaults": {
"build": {
"dependsOn": [
"^build"
],
"outputs": [
"{projectRoot}/dist",
"{projectRoot}/build",
"{projectRoot}/public/build"
]
}
}
}
若兩者皆未定義,Lerna 預設會快取儲存庫根目錄下的 dist
和 build
。
略過快取
有時候,你想要略過快取。舉例來說,如果你要量測指令的效能,你可以使用 --skip-nx-cache
旗標略過運算快取的檢查。
npx lerna run build --skip-nx-cache
npx lerna run test --skip-nx-cache
其他設定
其他設定任務和快取的方法,請參閱相關的 Nx 文件。