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 ci
npm ci
は、以下のような処理を実施するコマンドです。
node_modules
ディレクトリの削除package-lock.json
とpackage.json
の整合性のチェックpackage-lock.json
からnode_modules
を再現
これにより、npm ci
は元々使われていたバージョンのnpmパッケージをインストールします。当然、package-lock.json
を更新しません。