おいちゃんと呼ばれています

ウェブ技術や日々考えたことなどを綴っていきます

npm shrinkwrap を使うようにした

これまで npm shrinkwrap 使っていなかったんだけど、プライベートでやっているプロダクトで使うようにしたのでメモ。

3行まとめ

  • npm shrinkwrap すると npm-shrinkwrap.json が生成される
  • npm 3系では npm-shrinkwrap.jsondeependencies のパッケージは記載されているが、devDependencies のパッケージは記載されないのがデフォルトの挙動。devDependencies を含めるには --dev オプションを付ける
  • npm@4.0.1 からは npm-shrinkwrap.jsondevDeependencies のパッケージを含めるのがデフォルトの挙動。除外するには --production オプションを付ける

きっかけ

サーバーを移設した際に新しいサーバーで npm install したらパッケージ間の依存関係が壊れた。同様のことはこれまでにたしか 2回ほどあって、3回目のときにはカイゼンしようと心に決めていたのでやった。

$ npm install
...
npm WARN xxx requires a peer of yyy but none was installed.

どうして Yarn ではないのか?

Yarn を使ってもパッケージのバージョンを固定してくれるので、今回の問題に対してそれでも解決できたのだけれど。

しかし Yarn は別のプロジェクトで使っていて、つまり経験があるので、経験が無いほうの npm shrinkwrap という手段を選んだ。何かしらのヒントが得られるかもしれないと思って。

環境

手元の Mac の環境。ただし、後述するが npm のバージョンは途中で上げた。

$ node --version
v6.9.5
$ npm --version
3.10.10

ドキュメント

公式ドキュメント にざっと目を通した。日本語訳 もあったが、内容が古かったため。

事始め

node_modules を一旦真っ新にしてから npm shrinkwrap した。

$ rm -rf node_modules
$ npm install
$ npm shrinkwrap
wrote npm-shrinkwrap.json

npm-shrinkwrap.json が生成されたので git commit した。

ただし、この時点では npm-shrinkwrap.jsondeependencies のパッケージは記載されているが、devDependencies のパッケージは記載されていない(重要)

devDependencies も含めてバージョン固定する

どうして npm-shrinkwrap.jsondevDependencies のパッケージに含めないのがデフォルトの仕様なんだろう?複数の開発環境や CI の間で devDependencies パッケージのバージョンを揃えたいというのが自分の考えるフツウなのだが(Ruby の Bundler もそうだし) ともあれ --dev オプションを付ければ devDependencies のパッケージも含められるとのことなので実行。

$ npm shrinkwrap --dev

npm@4.0.1 からは devDependencies のパッケージも含めるのがデフォルト

なお 公式ドキュメントリリースノート にもあるように、npm のバージョン 4.0.1 からは npm-shrinkwrap.jsondevDependencies のパッケージに含めるのがデフォルトの挙動になった(含めたくない場合は --production オプションを付ける)

ついでなので npm のバージョンを 4系に上げた。

$ npm install --global npm@4
$ npm --version
4.5.0

おまけ)npm 4系で npm-shrinkwrap.json を作り直した

npm のバージョンを 4系に上げて、何か挙動が変わっただろうかという確認のため、やり直してみた。

$ rm -rf node_modules
$ rm npm-shrinkwrap.json
$ npm install
$ npm shrinkwrap
wrote npm-shrinkwrap.json

差分を見る。

[@ANGELINA.local maskedgirl-ui]$ git diff
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index 167b0e76..b136f399 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -6015,7 +6015,7 @@
     },
     "sinon": {
       "version": "2.2.0",
-      "from": "sinon@latest",
+      "from": "sinon@>=2.2.0 <3.0.0",
       "resolved": "https://registry.npmjs.org/sinon/-/sinon-2.2.0.tgz",
       "dev": true,
       "dependencies": {

なんだこれ。まさに、という記事を見つけた。

詳しくは上の記事の通りだが、今回 npm-shrinkwrap.json の差分が出たのは npm のバージョンを上げた影響ではなかった(記事を見ながら、ソースを追ってみたが、from の出力に関する箇所は npm@3.10.10 と npm@4.5.0 に差異はなかった)

まとめ

Yarn と較べて。Yarn は yarn install すれば yarn.lock も自動で生成されるのに対し、npm installnpm shrinkwrap が分かれている点が少し馴染めない。コマンドを打つのが面倒というより npm-shrinkwrap.json を意識せずに過ごしたいんだよなあ。

ともあれ npm パッケージのバージョン固定に成功した。めでたい。