【npm,yarn】今さら聞けないlockファイル
はじめに
今回はyarn.lockやpackage-lock.json等のlockファイルに関する内容です。
この辺りは検索をすれば同様の記事がヒットしますが、自信の備忘として改めて記事に起こしています。
package.jsonのバージョン表記方法について
lockファイルの役割を知るにはまず、package.jsonにライブラリをインストールした際の登録されるバージョンの表記方法について理解しておく必要があります。
例えば、hogehogeというライブラリを以下のコマンドでインストールしたとします。
yarn add hogehoge
するとpackage.jsonのdependenciesは下記のようになりました。
{
"hogehoge": "^1.2.1"
}
1.2.1というバージョンの先頭にキャレット^が付いています。
このようにyarnやnpmでライブラリをインストールした場合に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がインストールされたタイミングでfugafugaもnode_modulesに入っていると思います。
※ルートのpackage.jsonにfugafugaは記載されないため注意
異なるバージョンのライブラリをインストールする
さらに別なライブラリであるpunipuniをインストールしてみました。
するとルートのpackage.jsonのdependenciesは以下のようになりました。
{
"hogehoge": "^1.2.1",
"punipuni": "^4.3.0"
}
そしてnode_modules/punipuniのpackage.jsonには下記のような記述がありました。
{
"fugafuga": "^3.2.1"
}
punipuniもfugafugaに依存していますが、そのバージョンが異なります。
世に公開されているfugafugaの最新バージョンは3.3.1なので、ここでは^3.0.1と^3.2.1の両方を満たす3.3.1がインストールされました。
lockがない場合の問題点
ここまでの作業をAさんが行ったとします。
少し時間を置いてAさんと同様の環境を構築しようとしたBさんが、AさんがGitで共有したpackge.jsonを取得してyarn installを行いました。
この時hogehogeやfugafugaそしてpunipuniにさらに新しいバージョンが公開されていた場合、Bさんのローカルに構築した環境はAさんとは同じになりません。
なぜなら
{
"hogehoge": "^1.2.1",
"punipuni": "^4.3.0"
}
のように「X.X.X以降で、メジャーバージョンが変わらないバージョン」のような指定をしているため、より新しいバージョンが存在する場合、そちらがインストールされてしまうからです。
この問題を防いでいるのがlockファイルです。
yarn.lockはこうなっている
試しにyarn.lockファイルの中を見てみましょう。
Aさんがhogehogeとpunipuniを入れ終わった段階で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 installとyarn addの両方を使っていると、どちらか片方を使った方がよいといった旨の警告が出ます。
なぜかというとnpmはpackage-lock.jsonを、yarnはyarn.lockを参照するため、人によっては異なったバージョンがインストールされる可能性があるからです。
まとめ
今回はlockファイルについて、どんな役割を持っているかを紹介しました。
自分はJS開発を始めたての頃に、 「package.jsonさえあればどのバージョンが入っているかは分かるから、このよくわからないlockファイルはGitで管理しなくてもいいのでは?」 と思ってignoreしてしまったことがありますが、今となっては恐ろしい話です。
一見するとそれでも問題なく動作しているように見えますが、複数人で開発している場合は厳密にライブラリのバージョンを合わせた方が、バージョンの際による挙動の違いが発生しなくなるので安全です(当然ですが・・・)。
この記事が少しでも役立ちましたら幸いです。
Discussion