こんにちは。開発環境の深淵を覗き込み、日々のデプロイに心穏やかな時間を手に入れるためのガイドへようこそ。
多くのエンジニアが「なぜかCIでだけ落ちる」「npm installがタイムアウトする」という怪奇現象に頭を抱えます。これはツールが悪いのではなく、CI環境という「極めて不安定なネットワーク海域」に対する設定がデフォルトのまま(陸地向け)になっているからです。
今日は、npm/pnpmを使いこなし、CIを「止まらない自動化マシン」に変えるためのアーキテクチャ思考を伝授します。
—
1. なぜ「デフォルト設定」でCIを走らせてはいけないのか
npmやpnpmのデフォルト設定は、光回線が繋がった快適なオフィス環境を前提に設計されています。しかし、GitHub ActionsやJenkinsが動くクラウド上のコンテナは、時としてパケットロスが発生し、レジストリからの応答が遅延する「過酷な環境」に置かれます。
ここで重要なのは、「失敗した時にどう振る舞うか」という戦略(リトライ戦略)を明示的に定義することです。これを怠ると、巨大な `node_modules` の解決中に1秒の遅延が致命的なタイムアウトを引き起こし、ビルド全体を殺してしまいます。
—
2. 現場の生存率を上げる:.npmrcの最適解
CI環境のルートディレクトリに置く `.npmrc` は、単なるレジストリ設定ファイルではありません。これはネットワーク耐性を定義する防壁です。
1. タイムアウトを緩和し、低速なネットワークでも根気強く待つ
デフォルトは30000ms(30秒)ですが、CIでは倍の60秒以上に引き上げます
fetch-retry-maxtimeout=60000
2. リトライ回数を増やす
一時的なパケットロスによる断絶を、自動再試行で「無かったこと」にします
fetch-retries=5
3. リトライ間隔を指数関数的に増大させる
ネットワークが混雑している時に連続で叩くと遮断されるリスクがあるため
fetch-retry-mintimeout=10000
4. 並列度(Concurrency)を制御する
CPUやネットワークが貧弱なCIノードで「同時接続数」を絞り、接続過多によるエラーを防ぐ
max-sockets=5
なぜこれが必要なのか?
`max-sockets` を制限することで、一度に全てのパッケージを同時にダウンロードしようとする「暴走」を防ぎます。ネットワークの帯域を専有せず、確実に一つずつ(あるいは数個ずつ)積み上げることで、結果的にビルド完了までの時間は短縮され、成功率は劇的に向上します。
—
3. レジストリの「Failover」設計:透過的な切り替え
もし公式レジストリ(registry.npmjs.org)がダウンしていたら?あるいは、地理的に遠くレスポンスが悪い場合は?
実務の現場では、「メインレジストリがダメなら、ミラーを使ってでも完走させる」というフェイルオーバー戦略が求められます。
pnpmを使用している場合、特定のスコープに対してミラーを指定したり、CIの環境変数でレジストリを動的に注入する構成が最強です。
CI環境で実行するコマンドのテンプレート
ネットワーク断絶時に、環境変数でレジストリを切り替えるラッパー
npm_config_registry=”https://registry.npmjs.org”
FAILOVER_REGISTRY=”https://registry.npmmirror.com”
pnpmの実行例
ネットワーク疎通が不安な場合は、まず高速なミラーを試す設計にする
pnpm install –registry=$npm_config_registry || pnpm install –registry=$FAILOVER_REGISTRY
このように、CIのスクリプトは「一度の成功」を前提とせず、「失敗した時のバックアッププラン」をコードとして書き込むことが、プロフェッショナルなDevOpsの作法です。
—
4. 精度高い「HelloWorld」:CIでの成功確認
導入の第一歩として、以下のスクリプトをCIのステップに組み込んでみてください。これが通れば、あなたの環境は世界レベルの安定性を手に入れたと言えます。
GitHub Actionsの例
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: ’18’
cache: ‘pnpm’ # pnpmのキャッシュ機構を有効化し、ネットワーク負荷を最小限に
- name: Install Dependencies with Resilience
run: |
# ネットワークの安定性を確認しつつインストール
pnpm config set fetch-retries 5
pnpm config set fetch-retry-mintimeout 10000
pnpm install –frozen-lockfile
env:
# CI環境でのレジストリ固定
NPM_CONFIG_REGISTRY: https://registry.npmjs.org
この設定がもたらす「計り知れない利益」
- 心理的安全性: 「またビルド落ちてる…」という確認作業から解放されます。
- コスト削減: リトライによるCI時間の浪費(分単位の課金)を抑制します。
- コードへの集中: インフラ由来のトラブルに時間を奪われず、本来書くべきビジネスロジックに没頭できるようになります。
—
最後に:ツールを使いこなすということ
パッケージ管理ツールは単なる「ダウンロードソフト」ではありません。それは、あなたの開発ライフサイクルの血液を循環させる「インフラストラクチャ」です。
設定ファイルをただコピペするのではなく、「なぜこの数値なのか?」「もしネットワークが数秒切れたらどうなるか?」という視点を持ってください。その思考こそが、あなたを単なるプログラマーから、システムを俯瞰できる「アーキテクト」へと押し上げる鍵になります。
さあ、今日の設定で、あなたのCI環境を鉄壁のものに進化させましょう。何かあれば、いつでもまた聞きに来てくださいね。