dependenciesとdevDependencies、package-lock.jsonの役割
dependenciesとdevDependencies、package-lock.jsonの役割
npm install は毎日使っているのに、package.json と package-lock.json が実際に何を管理しているのか、自分でも意外と曖昧なままだったので、調べたときのメモです。
依存の種類、バージョン範囲の記号、lockファイルの役割を押さえておくと、「なぜか動かない」をだいぶ減らせるみたいです。
まず dependencies と devDependencies の違い
package.json には依存の置き場所が2つあります。
{
"dependencies": {
"react": "^19.0.0"
},
"devDependencies": {
"typescript": "^5.7.0",
"prettier": "^3.4.0"
}
}
違いは「アプリの実行時に必要かどうか」です。
| dependencies | devDependencies | |
|---|---|---|
| 内容 | 実行時に必要なもの | 開発・ビルド時だけ必要なもの |
| 例 | react, next | typescript, eslint, prettier |
| インストールコマンド | npm install パッケージ名 | npm install -D パッケージ名 |
ライブラリ(パッケージ)を作って公開する場合、この区別は特に重要です。利用者に入るのは dependencies だけで、devDependencies は入りません。テストツールを誤って dependencies に入れると、利用者に不要なものまで配ってしまうので、ここは注意です。
一方、アプリ(最終成果物)の開発では、ビルドツールでバンドルするので実行時の区別はあいまいになりますが、意図を表すドキュメント として正しく分けておくと、依存の見通しがよくなります。
バージョン範囲の記号
バージョン指定の先頭に付く記号は、許容する更新の幅を表します。npmはセマンティックバージョニング(メジャー.マイナー.パッチ)に従います。
| 記号 | 例 | 許容範囲 |
|---|---|---|
^ | ^1.2.3 | 1.x.x(メジャー据え置き、マイナー以下は上げる) |
~ | ~1.2.3 | 1.2.x(パッチのみ上げる) |
| なし | 1.2.3 | その版に固定 |
既定の ^ は「破壊的変更(メジャー更新)はしないが、機能追加やバグ修正は取り込む」という意味です。npm install のとき、この範囲内で最新のものが選ばれます。
なぜpackage-lock.jsonが要るのか
ここで問題になるのが、^1.2.3 のような 範囲指定だと、いつインストールするかで実際の版が変わる ことです。今日は 1.2.3、来週には 1.4.0 が入るかもしれません。これだと「自分の環境では動くのに、同僚やCIでは違う版で動く」という再現性の問題が起きます。地味にこれでハマったことがあります。
package-lock.json はこれを解決します。実際にインストールされた すべての依存(依存の依存まで含めて)の正確な版とハッシュ を記録して、ツリー全体を固定します。
{
"node_modules/react": {
"version": "19.0.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz",
"integrity": "sha512-..."
}
}
このファイルがあれば、誰がいつ npm install しても まったく同じ依存ツリー が再現されます。なので package-lock.json は必ずGitにコミットします。たまに .gitignore に入れてしまう例を見ますが、これはやらないほうがよさそうです。
installとciの使い分け
クリーンな環境(CIなど)では npm install ではなく npm ci を使うのが定石のようです。
npm install…package.jsonの範囲を満たすよう解決して、必要ならpackage-lock.jsonを更新するnpm ci…package-lock.jsonに 完全に従って インストールする。lockと矛盾があれば失敗する
npm ci は node_modules を作り直してロックどおりに入れるので、再現性が高くて速い です。CIやデプロイでは npm ci、依存を増やす作業中は npm install、と使い分けています。
まとめ
dependenciesは実行時に必要なもの、devDependenciesは開発時だけのもの^はメジャー据え置き、~はパッチのみ、記号なしは固定package-lock.jsonは依存ツリー全体の正確な版を固定して再現性を保証する。必ずコミットする- クリーン環境では
npm ciでロックに忠実に入れる
範囲指定の細かい記法はnpm公式のpackage.jsonドキュメントで確認できます。「動かないのは依存の版違いかも」と疑えるようになると、トラブルの切り分けがぐっと速くなりました。以上です。