第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つです👇
-
余計な「調整」をしない
npm installは状況により lock を更新したり、依存解決で悩んだりします。npm ciは「lockに書いてある通りに入れる」前提なので、ブレが減ります。 (docs.npmjs.com) -
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目線でスパッと整理していくよ 🏎️💨😆