CI/CDの「ビルド待ち時間」をゼロへ。GitHub Actionsキャッシュ戦略の真髄
こんにちは。開発環境を最適化し、チームの生産性を最大化することを生業としているアーキテクトです。
現場でよく耳にする嘆きがあります。「GitHub Actionsのビルドが遅い」。
数分、あるいは数十分のビルド待ち。これは単なる時間の浪費ではありません。エンジニアの「思考の断絶」を招く、開発体験(DX)における最大の敵です。
今回は、フロントエンド開発の命綱である `npm` / `yarn` / `pnpm` のキャッシュを、GitHub Actionsで極限まで最適化する設計思想を伝授します。単なるコピペコードではなく、「なぜキャッシュが効くのか」「どこを保存すべきか」という本質を理解することで、あなたのCI/CDパイプラインは劇的に速くなります。
—
1. なぜ「キャッシュ」がすべてを解決するのか
パッケージマネージャーがパッケージをインストールする際、実際には以下の3つの処理が行われています。
1. ネットワーク経由での取得: レジストリ(npm registryなど)への問い合わせ。
2. 解決(Resolution): バージョン間の依存関係(依存の依存)の計算。
3. 展開(Extraction): `node_modules` へのファイル書き出し。
これら全てを毎回ゼロから行うのは非効率です。特に `node_modules` は巨大で、ファイル数も膨大です。GitHub Actionsの `actions/setup-node` は、この「再利用可能な部分」を保存し、次回以降のジョブで復元することで、ネットワーク帯域とCPU資源を節約します。
—
2. 賢者の選択:各パッケージマネージャーのキャッシュ戦略
まずは、それぞれのツールが「どこにキャッシュを保持しているか」という内部仕様を理解しましょう。ここを間違えると、キャッシュのヒット率は0%になります。
pnpmのアーキテクチャ(推奨)
現在、最も効率的なのは `pnpm` です。`pnpm` はコンテンツアドレス指定可能なストア(Content Addressable Store)をローカルに持ちます。
- name: Setup pnpm
uses: pnpm/action-setup@v3
with:
version: 9
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: ‘pnpm’ # ‘pnpm’を指定するだけで、自動的にストアパスを探索してくれる
npm / yarn の場合
npmやyarnは、ユーザーディレクトリ配下にキャッシュディレクトリを持ちます。
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
# npmとyarn v1については、自動でキャッシュ設定が適用される
cache: ‘npm’
—
3. 「真の最適化」を行うためのYAML設定術
単に設定するだけでなく、「キャッシュのキー(Cache Key)」を意識することが重要です。キャッシュは「一致するキー」がないと復元されません。以下の設定は、最も安定し、かつ効率的なベストプラクティスです。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
# キャッシュ対象をnpm/yarn/pnpmのいずれかに設定
cache: ‘pnpm’
- name: Install Dependencies
# pnpm install はストアを先に参照するため、ここが爆速になる
run: pnpm install –frozen-lockfile
ここがプロの視点:なぜ `–frozen-lockfile` が必須なのか
CI環境では、ローカル環境と異なるバージョンがインストールされることを徹底的に排除すべきです。`package-lock.json` や `pnpm-lock.yaml` が変更されていない限り、キャッシュは100%再利用されます。ロックファイルを信頼し、CIでは「計算」させないことが高速化の鉄則です。
—
4. 精度高い動作確認:キャッシュが効いているか確認せよ
設定したら、GitHub Actionsの実行ログを見てください。初回実行時と2回目以降で、以下のメッセージが確認できるはずです。
- 初回: `Cache not found for key…`(キャッシュがないので新規作成)
- 2回目以降: `Cache restored successfully`(キャッシュを復元!)
もし2回目以降も `Cache not found` となる場合は、以下の項目を疑ってください。
1. ロックファイルのパス: `package.json` がリポジトリルートになく、サブディレクトリにある場合は `cache-dependency-path` オプションでパスを明示する必要があります。
2. キャッシュキーの不一致: Node.jsのバージョンやOSが変更されるとキーが変わります。
—
最後に:なぜこの設定で生産性が変わるのか
エンジニアの集中力は、待機時間に削られます。
「ビルドが終わるまでコーヒーを淹れに行こう」という時間は、実は「今やろうとしていたこと」を忘れる時間でもあります。
この設定をマスターすれば、GitHub Actionsの実行時間は物理的な通信速度から解放されます。数分かかっていた依存関係の解決が数秒で終わる。その浮いた時間で、あなたはより高度なアーキテクチャの設計や、コードの品質向上に集中できるのです。
「ツールに振り回される」のではなく、「ツールを御して、自分の思考を加速させる」。
これが、一流のエンジニアの歩き方です。ぜひ、今日からあなたのパイプラインにこのキャッシュ戦略を組み込んでみてください。劇的な変化に、きっと驚くはずですよ。