このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →
キャッシュの仕組み
タスク実行前、Lernaは計算ハッシュを生成します。この ハッシュ値が同一であれば、タスク実行結果も同一となります。
例えばlerna run test --scope=remixappのデフォルト計算ハッシュには以下が含まれます:
-
remixappとその依存関係の全ソースファイル -
関連するグローバル設定
-
外部依存関係のバージョン
-
Nodeバージョンなどユーザーが設定するランタイム値
-
CLIコマンドフラグ

この動作はカスタマイズ可能です。例:lintチェックはプロジェクトのソースコードとグローバル設定のみに依存し、ビルドではソースではなくコンパイル済みライブラリのdtsファイルを依存関係に指定できます。
ハッシュ生成後、Lernaは過去に同一計算が実行されたか確認します。まずローカルをチェックし、存在せずリモートキャッシュが設定されている場合はリモートを確認します。
該当計算が見つかると、Lernaはそれを取得・再生します。適切なファイルを適切な場所に配置し、ターミナル出力を再現します。ユーザーからは同じコマンドが高速で実行されたように見えます。

該当ハッシュが見つからない場合、Lernaはタスクを実行し、完了後に出力とターミナルログをローカル(および設定されていればリモート)に保存します。この処理は透過的に行われるため、ユーザーが意識する必要 はありません。
概念上は単純ですが、Lernaはユーザー体験向上のために最適化を実施しています。例えば:
-
Windows環境を含め、再現出力を正確にするためstdout/stderrをキャプチャ
-
ファイル再生位置を記憶することでI/Oを最小化
-
大規模タスクグラフ処理時に関連出力のみ表示
-
キャッシュミス診断機能の提供など、多数の最適化
ワークスペースが成長すると、タスクグラフは次のようになります:

これらの最適化は非自明なワークスペースでLernaを実用可能にするために重要です。最小限の作業のみが実行され、残りは現状維持またはキャッシュから復元されます。
ソースコードハッシュの入力
アプリケーションやライブラリのビルド/テスト結果は、当該プロジェクトのソースコードと、(直接的・間接的に)依存する全ライブラリのソースコードに依存します。
Lernaはデフォルトで保守的です。lerna run test --scope=remixapp実行時、remixappディレクトリの全ファイルに加え、headerおよびfooterディレクトリ(remixappの依存関係)の全ファイルを考慮します。これにより不要なキャッシュミスが発生します。例えばfooterのspecファイル変更は、上記テスト結果に影響しないことが明白です。
より正確な設定例:
注記: "{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
が次の2つのコマンドと同一であることを意味します:
npx lerna run build --scope=header
npx lerna run build --scope=footer
キャッシュされる内容
Lernaはプロセスレベルで動作します。プロジェクトのビルド/テスト/リントなどに使用するツールに関係なく、結果はキャッシュされます。
Lernaはコマンド実行前に標準出力/標準エラー出力を収集するフックを設定します。すべての出力はキャッシュされ、キャッシュヒット時に再生されます。
Lernaはコマンドで生成されたファイルもキャッシュします。ファイル/フォルダのリストはプロジェクトの package.json の outputs プロパティに定義されます:
注記: "{projectRoot}" と "{workspaceRoot}" はタスクランナーがサポートする特殊構文です。コマンド実行時に内部で適切に展開されるため、固定パスで置き換えるべきではありません。これらを置換すると設定の柔軟性が損なわれます。
{
"nx": {
"targets": {
"build": {
"outputs": ["{projectRoot}/build", "{projectRoot}/public/build"]
}
}
}
}
特定のターゲットに対する outputs プロパティがプロジェクトの package.json で定義されていない場合、Lernaは nx.json の targetDefaults セクションを参照します:
{
...
"targetDefaults": {
"build": {
"dependsOn": [
"^build"
],
"outputs": [
"{projectRoot}/dist",
"{projectRoot}/build",
"{projectRoot}/public/build"
]
}
}
}
どちらでも定義されていない場合、Lernaはリポジトリルートの dist と build をデフォルトでキャッシュします。