メインコンテンツまでスキップ

第09章:npm ciで“速くて再現できる”依存導入 🧼⚡️📦

この章はひとことで言うと、**「Docker/CIでは npm install より npm ci を基本にしよう」**です 😎✨ 理由はシンプルで、**速い+毎回同じ結果(再現性)**になりやすいから! (docs.npmjs.com)


1) npm ciって何者?(npm installとの違い)🧠💡

npm ci は、公式に「自動化された環境(CIやデプロイ等)でのクリーンインストール向け」と説明されています。 (docs.npmjs.com)

主な違いはこの5つ👇(ここ超重要!)

  • package-lock.json(または npm-shrinkwrap.json)が必須
  • package.json と lock の中身がズレてたらエラーで止まる(勝手に直さない)
  • 依存を1個だけ追加、みたいなのはできない(プロジェクト丸ごと)
  • 既に node_modules があれば、消してから入れ直す
  • package.json や lock を書き換えない(結果が“凍結”される) (docs.npmjs.com)

イメージ:

  • npm install → “状況を見ていい感じに整える” 🧹
  • npm ci → “レシピ(lock)通りに黙々と作る” 🍳⚙️

2) なんで npm ci が速く感じるの?🏎️💨

ポイントは2つです👇

  1. 余計な「調整」をしない npm install は状況により lock を更新したり、依存解決で悩んだりします。 npm ci は「lockに書いてある通りに入れる」前提なので、ブレが減ります。 (docs.npmjs.com)

  2. Dockerのレイヤキャッシュと相性が良い 🧱✨ Dockerfileで package.json と lock だけ先にCOPYしてから npm ci すると、 アプリコードをいじっても「依存インストールの層」が再利用されやすくなります(第7〜8章の総仕上げ感!)😆👍


3) Dockerfileでの “鉄板の置き方” 🔩🐳

まずは基本形(小さくて強い)👇

## 依存だけ先にコピー(キャッシュを守る)
COPY package.json package-lock.json ./

## CI/コンテナ向け:クリーンにインストール
RUN npm ci

## その後にアプリ本体
COPY . .

さらに現場でよく使う“ちょい足し”👇

  • --no-audit --no-fund:ビルド中の追加通信や表示を減らして速く&静かに 🤫⚡️
  • --omit=dev:本番用だけ入れる(※この教材だと第19章で本格的にやるやつ!)

Docker公式ガイドでも npm ci を使い、さらに --no-audit --no-fund--omit=dev を組み合わせた例が載っています。 (Docker Documentation)


4) “npm ci が失敗する” あるある 😵‍💫➡️✅

あるあるA:package-lock.json が無い

npm ci は lock 必須です。 (docs.npmjs.com) ➡️ まずローカルで npm install を1回回して lock を作り、Gitにコミットしよう 📌

あるあるB:package.json を編集したのに lock を更新してない

npm ciズレを見つけるとエラーで止まる仕様です(むしろ良い!) (docs.npmjs.com) ➡️ npm install を実行して lock を更新 → 変更差分をコミット ✅

あるあるC:昔 --legacy-peer-deps 等のフラグ付きで lock を作った

これ地雷になりがち💣 lock作成時に依存ツリーの形が変わるフラグ(例:--legacy-peer-deps / --install-links)を使ったなら、npm ci 側も同じ条件が必要です。 (docs.npmjs.com) ➡️ 例として公式は、npm config set ... --location=project.npmrc に固定してコミット、を案内しています。 (docs.npmjs.com)

あるあるD:モノレポ(workspaces)で挙動がよく分からん

workspaces は「ルート1つで複数パッケージを扱う」仕組みで、npm install がリンク等を自動化します。 (docs.npmjs.com) npm CLI v11 の npm ci には workspace/workspaces 系の設定項目も用意されています(モノレポでも運用しやすくなってる)。 (docs.npmjs.com) ➡️ まずは ルートで npm ci が通る状態を作ってから、必要ならワークスペース単位に最適化、が安全ルートです 🛣️✨


5) 🧪ミニ演習:npm install vs npm ci を計測して“差”を体感しよう 📊⏱️

演習1:Windows(PowerShell)で時間を測る 🪟⌛️

同条件にするため、まず node_modules を消してから測るのがコツです(npm ci は自分で消すけど、比較のため揃える)🙂

## 1回目:npm install
Remove-Item -Recurse -Force node_modules -ErrorAction SilentlyContinue
Measure-Command { npm install }

## 2回目:npm ci
Remove-Item -Recurse -Force node_modules -ErrorAction SilentlyContinue
Measure-Command { npm ci }

結果をメモ📒✨

  • インストール秒数
  • 途中で「lock更新」や警告が出たか
  • npm ci が止まった場合はエラーメッセージ(次のAI活用で使う!)

演習2:Dockerビルドで差を感じる 🐳⚡️

Dockerfileの依存導入行だけを変えてビルドログを比較します。

  • A案:RUN npm install
  • B案:RUN npm ci

docker build --progress=plain . でログを見て、依存インストール工程の秒数をチェック 👀📝


6) 🤖AI活用:npm ci を“味方”にする質問テンプレ 💬✨

コピペでOKのプロンプト集です(CopilotでもChatGPTでも)🧠💪

(1) npm ci が落ちた原因の特定

  • 「この npm ci のエラーを貼るので、原因を3つに分類して。①lock不整合 ②peer deps ③スクリプト/環境。直し方も“最短手順”で。」

(2) lock差分のレビュー

  • 「この package-lock.json の差分、意図しない更新っぽい所ある?(依存が増えた/減った/バージョン飛んだ等)注意点を箇条書きで。」

(3) Dockerfile改善

  • 「このDockerfileで npm ci を最速にしたい。キャッシュが効くCOPY順、--no-audit --no-fund の入れどころ、やりすぎ注意点を教えて。」

(Docker公式ガイドが npm ci --no-audit --no-fund--omit=dev を例示しているので、改善案の方向性がブレにくいです 👍)(Docker Documentation)


7) まとめ:この章の“持ち帰りチェック” ✅🎁

  • Docker/CIでは依存導入を npm ci に寄せる 🧼
  • package-lock.json を必ずコミットする 📌 (docs.npmjs.com)
  • package.json と lock がズレたら、直してから通す(ズレはバグのサイン)🚨 (docs.npmjs.com)
  • --legacy-peer-deps みたいな“形が変わるフラグ”は .npmrc で固定するのが安全 🔒 (docs.npmjs.com)
  • 速度計測して「どれだけ得したか」を数字で残す 📊✨

次の章(第10章)では「じゃあ pnpm にしたらもっと速いの?どこが変わるの?」を、Docker目線でスパッと整理していくよ 🏎️💨😆