npm installしたら壊れた…はなぜ起きるのか

npm install を実行しただけなのに、昨日まで動いていたプロジェクトが突然動かなくなる。エラーが山のように出て、どこを直せばいいのか分からない。JavaScriptやフロントエンド開発をしていると、一度はそんな経験をしたことがあるのではないでしょうか。

先に大事なことを言ってしまうと、これは「npmが不安定だから」でも「自分の操作が下手だったから」でもないケースがほとんどです。npm install で壊れるように見える現象の多くは、依存関係の管理が持つ構造的な問題が表に出ているだけ、ということが少なくありません。

この記事では、「npm install したら壊れた」がなぜ起きるのかを、実際の開発現場でよくあるパターンを交えながら整理します。その上で、どう付き合えば被害を最小限にできるのか、現実的な対策まで落とし込みます。

「npm install したら壊れた」と感じる正体

多くの場合、npm install 自体が何かを壊しているわけではありません。npmは package.json に書かれた内容をもとに、必要なライブラリを取得しているだけです。

それでも「壊れた」と感じるのは、次のような変化が同時に起きているからです。

  • 依存ライブラリのバージョンが以前と変わっている
  • 間接的に使っているライブラリが更新されている
  • Node.js や npm のバージョン差が影響している

つまり、npm install は「トリガー」になっているだけで、原因はその裏にある依存関係の状態にあります。

なぜ依存関係は簡単に壊れたように見えるのか

セマンティックバージョニングの落とし穴

npmの世界では、セマンティックバージョニング(semver)が基本ルールです。例えば package.json に次のように書かれていることがあります。

{
  "dependencies": {
    "example-lib": "^1.2.0"
  }
}

この ^ は「1系の中であれば新しいバージョンを使ってよい」という意味です。一見便利ですが、ここに落とし穴があります。

  • マイナーバージョンアップでも挙動が変わることがある
  • バグ修正のつもりの変更が別の不具合を生むことがある

結果として、以前とは違うコードがインストールされ、アプリが壊れたように見えるのです。

直接依存と間接依存の見えにくさ

package.json に書いているのは「直接依存」だけです。しかし実際には、そのライブラリがさらに別のライブラリに依存しています。

  • A を使っている
  • A は内部で B を使っている
  • B がアップデートされる
  • A の動きが微妙に変わる

このような連鎖は珍しくありません。npm install をした瞬間に、間接依存が更新され、結果として動かなくなるケースは非常に多いです。

lockファイルがあるのに壊れる理由

「package-lock.json があるから大丈夫なはず」と思ったことがあるかもしれません。確かに lock ファイルは、同じ依存関係を再現するための重要な仕組みです。

ただし、次のような条件が重なると話は変わります。

  • lock ファイルが git に含まれていない
  • npm のバージョンが大きく違う
  • 一度 lock ファイルを削除して install してしまった

特に「とりあえず package-lock.json を消して npm install」は、状況を悪化させやすい行動です。依存関係が再解決され、以前とは別物の構成になる可能性があります。

実際によくある「壊れた」パターン

フロントエンドビルドが通らなくなる

npm install 後に、次のようなエラーが出ることがあります。

npm run build
Error: Cannot find module 'xxx'

これは、ビルドツールやプラグインの依存関係がずれた典型例です。webpack、Vite、Babel などは周辺ライブラリの影響を強く受けるため、小さな更新でも壊れたように見えがちです。

型定義エラーが突然増える

TypeScript を使っている場合、npm install 後に型エラーが大量発生することもあります。

  • @types 系パッケージの更新
  • 本体ライブラリとのバージョン不整合

これも npm install が直接の原因ではなく、依存関係の組み合わせが変わった結果です。

向いている人・向いていない人の話

ここまで読むと、「npmって怖い」と感じるかもしれません。ただし、これは npm がダメという話ではありません。

npm install と比較的うまく付き合えるのは、次のような人です。

  • lock ファイルの意味を理解している
  • バージョン固定の重要性を知っている
  • エラーを切り分ける前提で作業できる

一方で、次のような状況ではトラブルが起きやすくなります。

  • 依存関係をあまり意識せずに install を繰り返す
  • エラーが出たらまず lock ファイルを消す
  • Node.js や npm のバージョン差を考慮していない

これは能力の問題ではなく、前提知識と経験の差によるものです。

リスクと注意点

npm install 周りで特に注意したいのは、「一時的に直ったように見える対処」です。

  • エラーが出たから node_modules を消す
  • なんとなく npm install をやり直す
  • 警告を無視して先に進む

これらは短期的には解決したように見えても、別の環境や将来の install で再発するリスクがあります。根本原因を把握しないまま進めると、プロジェクト全体が不安定になります。

結局どうすればいいのか

npm install で壊れたと感じたときに、現実的にできる対策は次の通りです。

  • package-lock.json を必ず管理対象に含める
  • Node.js と npm のバージョンを揃える
  • 安易に lock ファイルを削除しない
  • 依存関係の更新はまとめてではなく段階的に行う

npm install は魔法のコマンドではありません。依存関係という「動く部品」を組み立て直す操作です。その性質を理解して付き合えば、「突然壊れた」という感覚はかなり減らせます。

結局のところ、npm install が怖いのではなく、仕組みを知らないまま使うことが一番のリスクです。少しだけ中身を意識することで、トラブルは確実にコントロールできるようになります。