npm shrinkwrap とは?
npm shrinkwrapは、Node.jsプロジェクトの依存モジュールのバージョンを固定するコマンドです。
使い方についてはこちらの記事が参考になります。
今回は、npm shrinkwrapをより安定して使うためのコツを記載しました。
1. CIを活用し、テストしたバージョンで固定しリリース
npm shrinkwrapコマンドではnpm-shrinkwrap.jsonというファイルが生成されます。
継続的インテグレーションのサービスを活用し、そこでテストしたバージョンで固定するとよいでしょう。
CIでのフローとすれば以下になると思います。
-
npm updateで、可能な限り新しいバージョンを利用 - テスト (
npm test) npm shrinkwrap-
npm-shrinkwrap.jsonを追加しコミット、別tagや別branchとしてpushする (リリース)
テストされた依存モジュールのバージョンを配布できるので、安定度が上がります。
またリリースtag, branchだけにnpm-shrinkwrap.jsonを作ることで、
開発ブランチでのpackage.jsonとnpm-shrinkwrap.jsonの二重管理の問題もなくなります。
2. devDependencies周りのバグを理解し、克服する
devDependenciesは、開発のみに必要でproductionには必要ない依存モジュール群です。
これらをnpm-shrinkwrap.jsonから省くことで、インストール速度が向上します。
公式ドキュメントには、devDependenciesは入らないと書いていますが、
npm v3はバグがあり、devDependenciesがいくつか混じってしまいます。
さらに興味深いことに、npm v2では別のバグがあり、必要なdependenciesが入らない状況があります。
(see https://github.com/npm/npm/issues/11189)
npm v3の場合
npm shrinkwrapは不必要なdevDependenciesを含んでしまいます。
gistに再現コードを載せました。
ソースは追っていませんが、devDependenciesのdependenciesが含まれるような結果になっています。
npm v2の場合
一方npm v2ではdevDependenciesをしっかり除去してくれます!
しかし、逆に必要なモジュールが入らない状況があります。
gistに再現コードを載せました。
devDependenciesを除去するときに、それがdependenciesのdependenciesであっても取り除くようになっています。
じゃあどうするか?
このままではproductionで安定して使う気になれません。
そこで、運用では下記のような操作を行うことでこのバグを克服することにしました。
rm -rf node_modules
npm install --production
npm shrinkwrap
こうすることで、npm v2およびv3において、必要十分なモジュールのみが書き込まれます。
しかし残念なことに、これだとテストしたバージョンでshrinkwrapできない問題があります...
そこでnpm v3限定であれば以下のコマンドも利用可能です。
npm prune --production
npm shrinkwrap
npm pruneによってproductionに必要ないモジュールが取り除かれるため、うまくいきます。
まとめ
-
npm-shrinkwrap.jsonをCIで作って自動リリースがよい -
devDependencies関連にバグがあることを理解し、それを乗り越える
結局どうするの
CIなどで下記のような順番でコマンドを実行するといいでしょう。
(npm v3を利用)
npm updatenpm testnpm prune --productionnpm shrinkwrapgit add npm-shrinkwrap.jsongit commit -m "vX.Y.Z"git tag vX.Y.Zgit push origin vX.Y.Z
(5-8はgitでtagをリリースする一例です)
↑を楽にやるライブラリ
CircleCIで、これを楽にやるnode-circleci-autoreleaseを作成しました。ぜひ利用してみてください。
CureApp/node-circleci-autorelease
shrinkwrapだけでなく、gh-pagesやnpm publishなど、リリース自動化周辺の操作を設定ファイル1つで管理できます。
次回、日本語で使い方の解説記事を書きます。