Node.jsで作られたアプリケーションをデプロイするときに、npm shrinkwrapを使って依存モジュールのバージョンまで固定した状態でインストールする方法を紹介します。
背景
npm install
で依存モジュールをインストールするとき、package.json
で ^1.2.3
や ~1.2.3
といったバージョン指定をしているモジュールが1つでもあると、semver に従って 1.2.5
などのより新しいバージョンがインストールされる可能性があります。
セマンティックバージョンの意味からすれば、1.2.3 が互換性のある 1.2.5 に置き換わっても同じように動作すべきですが、現実問題としてテストしたバージョンと本番にデプロイされるバージョンが意図せず変わってしまうのは気持ちが悪く、依存モジュールを含めてバージョンを固定する方法を調べました。
実現方法
まずは npm install
します。すると、package.json
に従って依存関係にあるモジュールが node_modules
以下にインストールされます。
$ cd myapp/
$ npm install
...
$ ls
node_modules/ package.json
次に npm shrinkwrap
します。すると、node_modules
にインストールされている全モジュールのバージョン情報が npm-shrinkwrap.json
というファイルに出力されます。直接依存しているモジュールだけでなく、間接的に依存しているモジュールも含まれていることが分かります。
$ npm shrinkwrap
wrote npm-shrinkwrap.json
$ ls
node_modules/ npm-shrinkwrap.json package.json
$ cat npm-shrinkwrap.json
{
"name": "myapp",
"version": "0.0.1",
"dependencies": {
"socket.io": {
"version": "1.1.0",
"from": "socket.io@^1.1.0",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.1.0.tgz",
"dependencies": {
"engine.io": {
"version": "1.4.0",
"from": "engine.io@1.4.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.4.0.tg
z",
"dependencies": {
"debug": {
"version": "1.0.3",
"from": "debug@1.0.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-1.0.3.tgz",
...
最後に、npm-shrinkwrap.json
がある状態で npm install
すると、今度は package.json
ではなく npm-shrinkwrap.json
に記載されたバージョンに固定されて各モジュールがインストールされます。めでたし、めでたし。
$ cd myapp/
$ ls
npm-shrinkwrap.json package.json
$ npm install
補足
私は Node.js の素人なので、この方法が一般に推奨される方法なのかが分かっていません。やりたいことは「開発環境で動作確認したバージョンと同じモジュールを本番環境で動かしたい」ということで、いくつかの選択肢のうちこの方法が一番良さそうに思えたというだけです。
- 開発環境で動作確認した node_modules ごとコミットし、それをそのまま本番環境にデプロイ
- 以前はこの方法を使っていたが、OSやアーキテクチャも違うので怪しいし、コミットするファイルも大量になってしまう
-
package.json
だけコミットし、本番環境でnpm install
する- 動作確認したバージョンとは異なるバージョンがインストールされることがあり、しかもバージョン違いのせいで
npm install
がコケたことがあった
- 動作確認したバージョンとは異なるバージョンがインストールされることがあり、しかもバージョン違いのせいで
-
npm-shrinkwrap.json
もコミットし、本番環境でnpm install
する- バージョンを固定してインストールできるので良さそう。ただし、リリース時にnpmサーバーがダウンしていたらリリースできない
もっと良い方法やデファクトな方法を知っている方がいましたら、ぜひフィードバックいただけると嬉しいです。