まず結論
node_modules が重いのは、自分が入れたパッケージだけでなく、そのパッケージが必要とする依存関係も大量に入るからです。
npm install を実行すると、プロジェクト直下に node_modules が作られます。
node_modules/
astro/
vite/
typescript/
...
見た目以上に多くのファイルが入るため、容量もファイル数も大きくなりがちです。
依存関係は木のようにつながる
自分が直接入れたパッケージが、さらに別のパッケージを必要とします。
your-app
-> framework-a
-> parser-b
-> renderer-c
-> helper-d
-> tool-e
-> parser-b
このように依存関係は木のように広がります。自分では1つしか入れていないつもりでも、その先に何十、何百のパッケージがあることがあります。
なぜファイル数が多いのか
JavaScriptのパッケージは、小さな責務ごとに分かれていることがあります。
たとえば、次のような小さな処理でも別パッケージになっている場合があります。
- 文字列を変換する
- パスを解決する
- 色を扱う
- 設定ファイルを読む
- globを処理する
小さい部品を組み合わせる文化は再利用しやすい一方で、ファイル数が増える原因にもなります。
重複が起きることもある
パッケージAとパッケージBが、同じパッケージCの違うバージョンを必要とすることがあります。
package-a -> package-c@1
package-b -> package-c@2
この場合、両方のバージョンが必要になることがあります。package managerはできるだけ共有しようとしますが、完全に1つへまとめられるとは限りません。
node_modules はコミットしない
通常、node_modules はGitにコミットしません。
理由:
- 容量が大きすぎる
- OSごとに差が出ることがある
- lockfileから再現できる
- 差分レビューが現実的ではない
代わりに、package.json とlockfileをコミットします。
commitする:
package.json
package-lock.json
commitしない:
node_modules/
消してよい場合
依存関係がおかしくなった時、node_modules を削除して入れ直すことがあります。
rm -rf node_modules
npm install
ただし、これは原因調査の代わりではありません。lockfile、Node.jsのバージョン、package managerの混在も確認します。
ポイント: node_modulesは成果物ではなく、依存関係から再生成される作業用フォルダです。
まとめ
node_modules が重い理由は、直接依存だけでなく、推移的依存や複数バージョンの依存が含まれるからです。
大事なのは、node_modules そのものを管理することではなく、package.json とlockfileで再現できる状態を保つことです。