先週、npm install
とnpm ci
について調べて考えたことを書いたのだけど、ドキュメントを読んで、頭の中で考えたことをまとめただけなので、これだけだとちょっと気持ち悪いなと思って。簡単ではあるけど実際の動作を確認することにした。
結果
だいたい想像どおりだった。今回のサンプルプロジェクトで実験した結果は次のとおり。
(1)と(2)は、キャッシュがない場合のnpm ci
とnpm install
の速さ。想像では「npm ci
の方が多少速いのかな?」と考えていたけどほぼ同じだった。node_modules
がない状態から始まるので、npm ci
はnpm_modules
を削除する必要がない。一方で、npm install
も既存のnode_modules
をチェックする必要がなくて、package.json
とpackage-lock.json
の内容をチェックするだけ。だから、やることがお互いにそんなに違わないってことなのかな。
(3)はnpm ci
でnode_modules
のキャッシュにヒットした場合。これはキャッシュのリストアが終われば終わりなので、いちばん速い。ただし、フォールバックは効かないので、キャッシュにヒットしなかった場合に、違うバージョンのキャッシュを利用することができず、no cacheの場合の(1)と同じだけの時間がかかることになる。
(4)はnpm install
でnode_modules
のキャッシュにヒットした場合。フォールバックを考慮する場合、npm install
を実行しておかないといけないので、その実行分の時間がかかる。今回は10秒程度。フォールバックを考慮しないなら、(3)と同じになる。
(5)はnpm install
でフォールバックにヒットした場合を想定したもの。キャッシュとちょっと差分のあるpackage-lock.json
を持たせてみたのだけど、差分が少なすぎてあまり(4)と時間に差がでなかった。もし、もっと差分がある場合は(4)より多少遅くなると思う。
(6)はnpm ci
で~/.npm
のキャッシュにヒットした場合。今回、動作確認をしてみて気づいたのだけど、~/.npm
の中はtar.gz
で圧縮されているので容量が小さい。そのため、展開後のnode_modules
のキャッシュからのリストア(20秒くらい)よりも展開前の~/.npm
のリストア(5秒弱)の方が速い。その後の、npm ci
の実行は想像してたとおり多少時間がかかる。
(7)はnpm ci
で~/.npm
のフォールバックにヒットした場合。これも差分が少ないからか(6)との差は見られなかった。
実験環境
適当にpackage.json
を書いてpackage-lock.json
を生成しただけのプロジェクトを用意して
CircleCIで実行して確認した。
最初はデフォルトのリソースクラス(medium)を使ってたのだけど、それだと処理が速くて差が分かりにくかったので、もうちょっとゆっくり確認したくてsmallに変えた。
まとめ
前回の記事と特に変わらず
- プロジェクトが小さいうちは、特に何も気にしなくていい
- プロジェクトが大きくなってきたら、
npm ci
+~/.npm
キャッシュでスピードと安全性の両方をとっておくといい - プロジェクトが大きくて、ちょっとでも速くしたいなら
npm install
+node_modules
キャッシュを使ってもいいけど、安全性の担保(lockが更新されるリスクを回避)は自分でやる必要がある
個人的にはnpm install
が好みだけど、素直にnpm ci
を選んでおくのが、将来的にプロジェクトを受け取った人に優しいんだろうなと思うので、仕事ならnpm ci
を選ぶかなと思った。
おまけ
CircleCIのNode.jsのOrbを参考にしたんだけど、install-packages
コマンドを使うと、~/.npm
をキャッシュしてnpm ci
を実行するみたいなので、これを使っておけばフォールバックもいい感じにやっておいてくれるので楽かな。
https://circleci.com/developer/ja/orbs/orb/circleci/node?version=5.0.3#commands-install-packages
すっきりした。