🔒

【npm,yarn】今さら聞けないlockファイル

2021/03/09に公開

はじめに

今回はyarn.lockpackage-lock.json等のlockファイルに関する内容です。
この辺りは検索をすれば同様の記事がヒットしますが、自信の備忘として改めて記事に起こしています。

package.jsonのバージョン表記方法について

lockファイルの役割を知るにはまず、package.jsonにライブラリをインストールした際の登録されるバージョンの表記方法について理解しておく必要があります。

例えば、hogehogeというライブラリを以下のコマンドでインストールしたとします。

yarn add hogehoge

するとpackage.jsondependenciesは下記のようになりました。

{
    "hogehoge": "^1.2.1"
}

1.2.1というバージョンの先頭にキャレット^が付いています。
このようにyarnnpmでライブラリをインストールした場合にpackage.jsonに書き込まれるバージョンにはいくつか種類があります。

その内容をまとめたのが下記表になります。

表記 意味
1.2.1 1.2.1で固定
>=1.2.1 1.2.1以降のバージョン(<,>などの不等号で指定)
1.2.x xはなんでもOK
^1.2.1 1.2.1以降で、メジャーバージョンが変わらない

大概のライブラリがキャレット付きのパターンを使用しているかと思います。

ライブラリもまたライブラリに依存している

この時点で、node_modulesの中にhogehogeライブラリが入っていますが、その中にもさらにpackage.jsonがあるかと思います。
そしてその中のdependenciesに以下の記載があったとします。

{
    "fugafuga": "^3.0.1"
}

これはhogehogeライブラリがfugafugaライブラリに依存していることを意味します。
パッケージマネージャーの機能として、参照先のライブラリもよしなにインストールしてくれるので、基本的にはhogehogeがインストールされたタイミングでfugafuganode_modulesに入っていると思います。
※ルートのpackage.jsonfugafugaは記載されないため注意

異なるバージョンのライブラリをインストールする

さらに別なライブラリであるpunipuniをインストールしてみました。
するとルートのpackage.jsondependenciesは以下のようになりました。

{
    "hogehoge": "^1.2.1",
    "punipuni": "^4.3.0"
}

そしてnode_modules/punipunipackage.jsonには下記のような記述がありました。

{
    "fugafuga": "^3.2.1"
}

punipunifugafugaに依存していますが、そのバージョンが異なります。
世に公開されているfugafugaの最新バージョンは3.3.1なので、ここでは^3.0.1^3.2.1の両方を満たす3.3.1がインストールされました。

lockがない場合の問題点

ここまでの作業をAさんが行ったとします。
少し時間を置いてAさんと同様の環境を構築しようとしたBさんが、AさんがGitで共有したpackge.jsonを取得してyarn installを行いました。

この時hogehogefugafugaそしてpunipuniにさらに新しいバージョンが公開されていた場合、Bさんのローカルに構築した環境はAさんとは同じになりません。
なぜなら

{
    "hogehoge": "^1.2.1",
    "punipuni": "^4.3.0"
}

のように「X.X.X以降で、メジャーバージョンが変わらないバージョン」のような指定をしているため、より新しいバージョンが存在する場合、そちらがインストールされてしまうからです。

この問題を防いでいるのがlockファイルです。

yarn.lockはこうなっている

試しにyarn.lockファイルの中を見てみましょう。
Aさんがhogehogepunipuniを入れ終わった段階でyarn.lockは以下のようになっています。

hogehoge@^1.2.1:
  version "1.3.1"
  resolved "https://......."
  integrity sha512-hogehogehoge
  dependencies:
    fugafuga "^3.0.1"

punipuni@^4.3.0:
  version "4.4.1"
  resolved "https://......."
  integrity sha512-punipunipuni
  dependencies:
    fugafuga "^3.2.1"

fugafuga@^3.0.1, fugafuga@^3.2.1:
  version "3.3.1"
  resolved "https://......."
  integrity sha512-fugafugafuga

lockファイルは 「依存関係まで含めて、実際にどのバージョンがインストールされているか」 を管理します。
それぞれのライブラリのversionの項目がそれにあたります。

パッケージマネージャーは基本的に、lockファイルがあればそちらの記載に従うので、lockファイルを共有することで 「誰がインストールしても同じバージョンがインストールされる」 ことを担保することができます。

npm installyarn addの両方を使っていると、どちらか片方を使った方がよいといった旨の警告が出ます。
なぜかというとnpmpackage-lock.jsonを、yarnyarn.lockを参照するため、人によっては異なったバージョンがインストールされる可能性があるからです。

まとめ

今回はlockファイルについて、どんな役割を持っているかを紹介しました。

自分はJS開発を始めたての頃に、 package.jsonさえあればどのバージョンが入っているかは分かるから、このよくわからないlockファイルはGitで管理しなくてもいいのでは?」 と思ってignoreしてしまったことがありますが、今となっては恐ろしい話です。

一見するとそれでも問題なく動作しているように見えますが、複数人で開発している場合は厳密にライブラリのバージョンを合わせた方が、バージョンの際による挙動の違いが発生しなくなるので安全です(当然ですが・・・)。

この記事が少しでも役立ちましたら幸いです。

Discussion