LoginSignup
41
27

More than 3 years have passed since last update.

npm,yarnのlockファイルの恩恵

Last updated at Posted at 2019-10-24

lockファイルの恩恵を確認したい!

Nodejsのモジュールをコマンドでインストールすると、
* npm installの場合 => package-lock.json
* yarn installの場合 => yarn-lock.json
がどれぞれ生成される。

なんかバージョンを固定するのに役立つと聞くけど、いまいちどんな恩恵があるのかわかってなかったので、動作を確認してみる。

環境

  • node : v12.13.0
  • npm : 6.12.0
  • yarn : 1.19.1

確認

npm, yarn でそれぞれlodashをinstallして、色々変更しながら入るバージョン確認していく。

lodashは2019/10/24の時点で、4系はv4.17.15まで、3系はv3.10.1までがnpmに公開されている。
https://www.npmjs.com/package/lodash

npmでの確認

lodash v3.0.0のインストール

適当なディレクトリを作成して、npmでlodashの3.0.0指定してをインストールする。

$ npm init -y
$ npm install lodash@3.0.0 --save

node_moduleに入っているlodashのバージョンを確認すると、期待通りにlodashの3.0.0がインストールされている。

$ grep '"version":' node_modules/lodash/package.json
  "version": "3.0.0"

このときのpackage.jsonとpackage-lock.json下記のようになる。

package.jsonのdependencies
  "dependencies": {
    "lodash": "^3.0.0"
  }
  • lodashのバージョン指定は^3.0.0と記述されて、少しゆるい指定の「3系の最新ちょうだい(3.0.0 <= x < 4.0.0)」となる。
package-lock.jsonのdependencies
  "dependencies": {
    "lodash": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.0.0.tgz",
      "integrity": "sha1-STNktxg6NxBNZSVfOLD+WGnL4P0="
    }
  }
  • インストールするバージョンは3.0.0であると記述される("version": "3.0.0"

node_modulesのみを削除して再インストール

node_modulesを削除してnpm installをすると...3.0.0がインストールされる。

$ rm -rf node_modules
$ npm install
$ grep '"version":' node_modules/lodash/package.json
  "version": "3.0.0"

package-lock.jsonとnode_modulesを削除して再インストール

node_modules一緒にpackage-lock.jsonを削除してnpm installをすると...3.10.1がインストールされる。

$ rm -rf node_modules package-lock.json
$ npm install
$ grep '"version":' node_modules/lodash/package.json
  "version": "3.10.1"

これはpackage.jsonでのlodashのバージョン指定が「3系の一番新しいやつ」とゆるい指定になっているため。

package.json抜粋
  "dependencies": {
    "lodash": "^3.0.0"
  }

package-lock.jsonがある間はしっかりバージョン指定されるが、なくなるとpackage.jsonのゆるい指定にひっぱられる。
また、このときにpackage-lock.jsonはその時のlodashのバージョンにロックされたもので再生成される。

package.jsonの記述を変更する(~3.0.0)

(一旦、lodashのバージョンを3.0.0で指定してインストールし直す)

package.jsonのlodashのバージョン指定方法を^3.0.0 => ~3.0.0へ変更する。

package.json抜粋
  "dependencies": {
    "lodash": "~3.0.0"
  }

この状態でnode_modulesを削除してnpm installをすると...3.0.0がインストールされる。

$ rm -rf node_modules
$ npm install
$ grep '"version":' node_modules/lodash/package.json
  "version": "3.0.0"

~3.0.0は 「3.0.0 <= x < 3.1.0」を取得する記述で、package-lock.jsonで指定されているバージョンが3.0.0なため、
package-lock.jsonに書かれているバージョンが採用される。

package.jsonの記述を変更する(^4.0.0)

package.jsonのlodashのバージョン指定方法を^3.0.0 => ^4.0.0へ変更する。

package.json抜粋
  "dependencies": {
    "lodash": "^4.0.0"
  }

この状態でnode_modulesを削除してnpm installをすると...4.17.15がインストールされる。

$ rm -rf node_modules
$ npm install
$ grep '"version":' node_modules/lodash/package.json
  "version": "4.17.15"

^4.0.0は 「4.0.0 <= x < 5.0.0」を取得する記述で、package-lock.jsonで指定されているバージョンが3.0.0だけど、
package.jsonの指定の範囲外なので、package-lock.jsonの内容は無視されて、4系の最新の4.17.15がインストールされる。

また、このときにpackage-lock.jsonはその時のlodashのバージョンにロックされたもので再生成される。

yarnでの確認

lodash v3.0.0のインストール

適当なディレクトリを作成して、yarnでlodashの3.0.0指定してをインストールする。

$ yarn init -y
$ yarn add lodash@3.0.0

node_moduleに入っているlodashのバージョンを確認すると、期待通りにlodashの3.0.0がインストールされている。

$ grep '"version":' node_modules/lodash/package.json
  "version": "3.0.0"

このときのpackage.jsonとpackage-lock.json下記のようになる。

package.jsonのdependencies
  "dependencies": {
    "lodash": "3.0.0"
  }
  • lodashのバージョン指定は3.0.0と記述されて、厳密に指定した「3.0.0のバージョンがほしい」となる。
yarn.lockのdependencies
lodash@3.0.0:
  version "3.0.0"
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.0.0.tgz#493364b7183a37104d65255f38b0fe5869cbe0fd"
  integrity sha1-STNktxg6NxBNZSVfOLD+WGnL4P0=
  • package.jsonでの「lodash指定は3.0.0」だった。(lodash@3.0.0:)
  • インストールするバージョンは3.0.0であると記述される(version "3.0.0"

node_modulesのみを削除して再インストール

node_modulesを削除してyarn installをすると...3.0.0がインストールされる。

$ rm -rf node_modules
$ yarn install
$ grep '"version":' node_modules/lodash/package.json
  "version": "3.0.0"

yarn.lockとnode_modulesを削除して再インストール

node_modules一緒にpackage-lock.jsonを削除してnpm installをすると...3.0.0がインストールされる。

$ rm -rf node_modules package-lock.json
$ yarn install
$ grep '"version":' node_modules/lodash/package.json
  "version": "3.0.0"

package.jsonでの指定がnpmとは違って厳密なので、3.0.0がインストールされる。
また、このときにyarn.lockがなくなっていたので、その時のlodashのバージョンにロックされたもので再生成される。(消す前と全く同じ内容)

package.jsonの記述を変更する(~3.0.0)

package.jsonのlodashのバージョン指定方法を^3.0.0 => ~3.0.0へ変更する。

package.json抜粋
  "dependencies": {
    "lodash": "~3.0.0"
  }

この状態でnode_modulesを削除してyarn installをすると...3.0.1がインストールされる。

$ rm -rf node_modules
$ yarn install
$ grep '"version":' node_modules/lodash/package.json
  "version": "3.0.1"

yarn.lock内での記述は、

  • package.jsonでの「lodash指定は3.0.0」だった。(lodash@3.0.0:)

となっていたけど、package.jsonでの指定方法が~3.0.0に変更したせいで、yarn.lockの記述と一致しなくなったため、yarn.lockの指定が無視されるようになる。

また、このときにyarn.lockはその時のlodashのバージョンにロックされたもので再生成される。

package.jsonとyarn.lockの記述を同じように変更する(~3.0.0)

(一旦、lodashのバージョンを3.0.0で指定してインストールし直す)

package.jsonyarn.lockバージョン指定をそれぞれ~3.0.0へ変更する

package.json抜粋
  "dependencies": {
    "lodash": "~3.0.0"
  }
yarn.lockのdependencies
lodash@~3.0.0:
  version "3.0.0"
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.0.0.tgz#493364b7183a37104d65255f38b0fe5869cbe0fd"
  integrity sha1-STNktxg6NxBNZSVfOLD+WGnL4P0=

この状態でnode_modulesを削除してnpm installをすると...3.0.0がインストールされる。

$ rm -rf node_modules
$ yarn install
$ grep '"version":' node_modules/lodash/package.json
  "version": "4.17.15"

package.jsonの指定が変更されたが、一緒にyarn.lockの指定も変更したため、それぞれの指定がずれなかったためyarn.lockの指定されたバージョンがインストールされた。

まとめ

package-lock.jsonyarn.lockでバージョンをロックしてくれた。
ただ、package.jsonを変更したときの、無視する条件が異なった。

  • package-lock.json(npm)
    • package.jsonの指定内容がpackage-lock.jsonの指定範囲を外れてしまったら、無視される。
    • 逆に、指定範囲内なら記述を変えてもpackage-lock.jsonは有効
  • yarn.lock(yarn)
    • package.jsonの指定内容が、yarn.lock内での記述方法が一致しなくなったら、無視される。

npmからyarnに乗り換えるときとか、package.jsonのバージョン指定を整理するときとかはこの仕様の違いに注意したほうが良さそう。

おまけ

調べている途中で気づいたけど、 npm install lodash@3.0.0yarn add lodash@3.0.0でpackage.jsonの記述内容が変わるのが意外だった。個人的にはバージョン指定はしっかり固定したほうが安心派なので、yarnのほうが好き。

あと、

  • package.jsonの指定内容がpackage-lock.jsonの指定範囲を外れてしまったら、無視される。

この挙動はnpmのv6.12.0あたりからの仕様っぽい。
nodeのv10とかで使われる、 npmのv6.4.1ではこの挙動はしないで、package-lock.jsonの指定は勝手にはずれなかった。
好みの問題かもしれないけど、nodeのバージョンアップ時(v10 => v12)になにか地雷を踏みそうで怖い。

41
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
27