メインコンテンツへスキップ
非公式ベータ版翻訳

このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →

キャッシュの仕組み

タスク実行前、Lernaは計算ハッシュを生成します。このハッシュ値が同一であれば、タスク実行結果も同一となります。

例えばlerna run test --scope=remixappのデフォルト計算ハッシュには以下が含まれます:

  • remixappとその依存関係の全ソースファイル

  • 関連するグローバル設定

  • 外部依存関係のバージョン

  • Nodeバージョンなどユーザーが設定するランタイム値

  • CLIコマンドフラグ

computation-hashing

この動作はカスタマイズ可能です。例:lintチェックはプロジェクトのソースコードとグローバル設定のみに依存し、ビルドではソースではなくコンパイル済みライブラリのdtsファイルを依存関係に指定できます。

ハッシュ生成後、Lernaは過去に同一計算が実行されたか確認します。まずローカルをチェックし、存在せずリモートキャッシュが設定されている場合はリモートを確認します。

該当計算が見つかると、Lernaはそれを取得・再生します。適切なファイルを適切な場所に配置し、ターミナル出力を再現します。ユーザーからは同じコマンドが高速で実行されたように見えます。

cache

該当ハッシュが見つからない場合、Lernaはタスクを実行し、完了後に出力とターミナルログをローカル(および設定されていればリモート)に保存します。この処理は透過的に行われるため、ユーザーが意識する必要はありません。

概念上は単純ですが、Lernaはユーザー体験向上のために最適化を実施しています。例えば:

  • Windows環境を含め、再現出力を正確にするためstdout/stderrをキャプチャ

  • ファイル再生位置を記憶することでI/Oを最小化

  • 大規模タスクグラフ処理時に関連出力のみ表示

  • キャッシュミス診断機能の提供など、多数の最適化

ワークスペースが成長すると、タスクグラフは次のようになります:

cache

これらの最適化は非自明なワークスペースでLernaを実用可能にするために重要です。最小限の作業のみが実行され、残りは現状維持またはキャッシュから復元されます。

ソースコードハッシュの入力

アプリケーションやライブラリのビルド/テスト結果は、当該プロジェクトのソースコードと、(直接的・間接的に)依存する全ライブラリのソースコードに依存します。

Lernaはデフォルトで保守的です。lerna run test --scope=remixapp実行時、remixappディレクトリの全ファイルに加え、headerおよびfooterディレクトリ(remixappの依存関係)の全ファイルを考慮します。これにより不要なキャッシュミスが発生します。例えばfooterのspecファイル変更は、上記テスト結果に影響しないことが明白です。

より正確な設定例:

注記: "{projectRoot}" と "{workspaceRoot}" はタスクランナーがサポートする特殊構文です。コマンド実行時に内部で適切に展開されるため、固定パスで置き換えるべきではありません。これらを置換すると設定の柔軟性が損なわれます。

nx.json
{
"namedInputs": {
"default": ["{projectRoot}/**/*"],
"prod": ["!{projectRoot}/**/*.spec.tsx"]
},
"targetDefaults": {
"build": {
"inputs": ["prod", "^prod"]
},
"test": {
"inputs": ["default", "^prod", "{workspaceRoot}/jest.config.ts"]
}
}
}

この設定では、ビルドスクリプトは remixappheaderfooter のテスト以外のファイルのみを考慮します。テストスクリプトは、テスト対象プロジェクトのすべてのソースファイルと、その依存関係のテスト以外のファイルのみを考慮します。また、テストスクリプトはワークスペースのルートにあるJest設定ファイルも考慮します。

ランタイムハッシュの入力

ターゲットはランタイム値にも依存する可能性があります。

nx.json
{
"targetDefaults": {
"build": {
"inputs": [{ "env": "MY_ENV_NAME" }, { "runtime": "node -v" }]
}
}
}

引数ハッシュの入力

最後に、ソースコードハッシュ入力とランタイムハッシュ入力に加え、Lernaは引数も考慮する必要があります。例えば、lerna run build --scope=remixapplerna 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.jsonoutputs プロパティに定義されます:

注記: "{projectRoot}" と "{workspaceRoot}" はタスクランナーがサポートする特殊構文です。コマンド実行時に内部で適切に展開されるため、固定パスで置き換えるべきではありません。これらを置換すると設定の柔軟性が損なわれます。

E.g. packages/my-project/package.json
{
"nx": {
"targets": {
"build": {
"outputs": ["{projectRoot}/build", "{projectRoot}/public/build"]
}
}
}
}

特定のターゲットに対する outputs プロパティがプロジェクトの package.json で定義されていない場合、Lernaは nx.jsontargetDefaults セクションを参照します:

nx.json
{
...
"targetDefaults": {
"build": {
"dependsOn": [
"^build"
],
"outputs": [
"{projectRoot}/dist",
"{projectRoot}/build",
"{projectRoot}/public/build"
]
}
}
}

どちらでも定義されていない場合、Lernaはリポジトリルートの distbuild をデフォルトでキャッシュします。

キャッシュのスキップ

場合によってはキャッシュをスキップしたいことがあります。例えばコマンドのパフォーマンスを測定する場合、--skip-nx-cache フラグを使用して計算キャッシュのチェックをスキップできます。

npx lerna run build --skip-nx-cache
npx lerna run test --skip-nx-cache

追加の設定

タスク実行とキャッシュに関する追加の設定方法については、関連する Nx ドキュメントを参照してください。