package-lock.jsonからnode_modulesを(再)生成する方法のメモです。package.jsonとpackage-lock.jsonの違いも含めて、なぜそれが必要となるか、実際にどのようにして実行するか、をまとめます。
package.jsonとpackage-lock.jsonの違い
そもそも二つのファイルにはどのような違いがあるのでしょうか?
- package.json
- そのプロジェクトに必要なパッケージのバージョン(の範囲)
- その他(scriptsなどプロジェクト全体の設定項目)
- package-lock.json
npm installによって実際にインストールしたパッケージのバージョン
package.jsonの仕組み
とあるnpmパッケージであるhogeをインストールした時、通常最新バージョンが 1.0.0 の場合、package.jsonのdependenciesには、次のような行が追加されます。
"hoge": "^1.0.0"これは、 hogeのバージョン1.x.x に該当する最新のバージョンという意味です。
ですので、次にこのpackage.jsonを使って npm installするまでにhoge v1.0.1が公開されていた場合、次にnpm installを行う人の開発環境に、hoge v1.0.1がインストールされます。
package-lock.jsonの仕組み
package-lock.jsonは通常、npm installをした場合に自動的に生成されるファイルです。このファイルを直接いじる必要があることはほとんどないため、意識せずに使っている方が多いでしょう。
このファイルには、実際にインストールされたnpmパッケージのバージョンが記載されています。
例えば、上記のpackage.jsonの例で言うと、初めにhogeをインストールした人の環境では、
"hoge": {
"version": "1.0.0"
...
}という記述が追加されます。
しかし、hogeの新バージョンがリリースされた後にnpm installを実施すると、このファイルに変更が加わることになります。
"hoge": {
"version": "1.0.1"
...
}npm installはpackage.jsonの記述に従い、指定された範囲内の最新バージョンであるhoge v1.0.1をインストールしました。そのため、実際にインストールされたバージョンを記載するpackage-lock.jsonの記載に変更が加わったわけです。
なんで二つに分かれているのか?

npmパッケージはメジャーバージョンと呼ばれる一番左の数字が変わらない限り、互換性があることはほとんどです。そのため、使うときに最新バージョンが更新されていた場合に、v1.0.0ではなくv1.0.1をインストールしてくれるpackage.jsonの記載はとても便利なものです。
しかし、問題が発生する場合もあります。
例えば、hoge v1.0.1に致命的なバグがある場合を考えます。
この時、npm installを実施した人の環境では、単にnpm installをしただけの状態なのに元々は動いていたはずのプロジェクトが動きません。「何もしてないけど壊れた」状態です。

ここでpackage-lock.jsonが更新されていることに気づくでしょう。元々は、v1.0.0を使っていたことを知り、v1.0.1にバグがある可能性に気づくことになります。
更新されたバッケージが一つの場合は、そのパッケージを元のバージョンまでダウングレードすればいいわけですが、複数のパッケージがアップデートされているとちょっと面倒です。
そこで、package-lock.jsonをベースに元々のバージョンと全く同じものをまとめてインストールする方法があります。
package-lock.jsonからnode_modulesを生成する
npm cinpm ciは、以下のような処理を実施するコマンドです。
node_modulesディレクトリの削除package-lock.jsonとpackage.jsonの整合性のチェックpackage-lock.jsonからnode_modulesを再現
これにより、npm ciは元々使われていたバージョンのnpmパッケージをインストールします。当然、package-lock.jsonを更新しません。


