package.jsonとpackage-lock.jsonの違い。package.jsonはなぜ必要なのか?
package.jsonはなぜ必要なのか?
npm installをするときになぜpackage.jsonとpackage-lock.jsonがあるのか不思議ですよね。package.jsonだけではダメなのでしょうか?ダメだとしたらなぜダメなのでしょうか?
tl;dr
package.jsonにはアプリケーションが依存するnpmモジュールを記載できるが、依存モジュールが依存するモジュール(=孫依存モジュール)に関しては何も指定できない。インストールした孫依存モジュールのバージョを記録しておき、孫依存モジュールの新しいバージョンが出たとしてもバージョンを固定しておくためにはpackage-lock.jsonを使う。
以下でもう少しだけ詳しく書いていきます。
package.jsonだけでは、アプリケーションが依存するすべてのnpmモジュールのバージョンを固定できないため別の仕組みが必要であり、その仕組がpackage-lock.jsonです
package.jsonには自分が作っているアプリケーションが直接依存するnpmモジュールが記載されます。
たとえば、自分のアプリケーションがaaaとbbbという2つのnpmモジュールに依存しており、それぞれ1.1.1と2.2.2が最新バージョンだったとし、以下のようにnpm installしたとしましょう。
npm install aaa
npm install bbb
すると、package.jsonのdependenciesには
//・・・省略・・・
"dependencies": {
"aaa": "^1.1.1",
"bbb": "^2.2.2"
},
// ・・・省略・・・
と記載されます。
^(キャレット)はメジャーバージョン固定の意味
上記のpackage.json例の^(キャレット)に気がついたかもしれません。^(キャレット)はメジャーバージョン(バージョンの3桁のうち1番左の桁の数字)のみを固定するという意味です。
なので、後になれば1.1.2や1.2.0などの新しくリリースされ、リリース後にnpm installすると新しいバージョンがインストールされてしまい、バージョンが固定されません。
対してpackage-lock.jsonには、npm installしたときの依存モジュールのバージョンが^(キャレット)なしで記録されます。その後にnpm installするときにはpackage.jsonよりpackage-lock.jsonの情報が優先されてインストールされるため、バージョンが固定できます。
しかし、ここで疑問がでて来ると思います。
package-lock.jsonを使わずともpackage.jsonの中に^(キャレット)を使わずバージョン指定をすれば良いのではないか?
package.jsonの中に^(キャレット)を使わないこともできます。npm install aaa --save-exact がまさにそのためのコマンドです。
しかし、これでは解決できない問題が1つあります。依存モジュールが依存しているモジュールのバージョン固定です。(依存モジュールが依存しているモジュールのことを孫依存モジュールとここでは言いましょう)
package.jsonには自信のアプリケーションが直接依存しているモジュールをのバージョンを固定できますが、孫依存モジュールのバージョンに関してはpackage.jsonではコントロールができません。
例えば、aaaモジュールがcccモジュールに依存しているとしましょう。aaaのあるバージョンがcccのどのバージョンを使うかは私達では決められません。aaaモジュール(の作者)が決めるものであり、package.jsonの中で指定することはできません。
しかし、package-lock.jsonを使うことでnpm installでインストールした孫依存モジュールを記録しておくことができ、cccモジュールの新しいバージョンがリリースされたとしても以前インストールしたバージョンをインストールすることができます。
まとめ
package.jsonとpackage-lock.jsonの違い、なぜpackage-lock.jsonが必要なのか、私が自分で調べたときに手間取ったので調べた結果を書いてきました。
同じように疑問に思った方の参考になれば。
お役に立ちましたぜひスキをお願いいたします。もっと記事を書くモチベーションになります
この記事が気に入ったらサポートをしてみませんか?