yarn --frozen-lockfileで環境によるバージョン差異をなくそう
npm
やyarn
を利用して複数人で作業をしているとnpm install
やyarn
でパッケージを更新しただけでyarn.lock
やpackage-lock.json
に更新が走る場合はあります。
いろいろなプロジェクトに関わっていると定期的にここではまる人が結構いるのでこの挙動と解決策を解説してみようと思います。
yarn.lock
やpackage-lock.json
に更新が走るのか
なぜパッケージのインストール時にnpm install
やyarn
を利用すると、package.json に記載された依存関係のバージョンを元に、実際にインストールするパッケージのバージョンが決定されます。
その際に生成されるのがnpm
の場合はpackage-lock.json
が、yarn
の場合はyarn.lock
が生成されます。
これらのファイルは現在インストールを行ったパッケージのバージョンが依存関係も含めて記述されています。
たとえば、yarn add exsample-package
とパッケージをインストールした場合に以下のようなpackage.json
が生成されたとします。
{
"name": "example-project",
"version": "1.0.0",
"dependencies": {
"exsample-package": "^1.2.3",
}
}
実際にこのタイミングではexsample-package
は1.2.3
のものがインストールされており、yarn.lock
にもその情報が記述されています。
数日後にyarn
コマンドでパッケージの更新を行います。この際にインストールされるexsample-package
のバージョンは1.2.3
とは限らず^1.2.3
の範囲つまりpackage.json
のバージョン指定の冒頭にキャレット(^)があるため1.2.3
から 2.0.0
までで最新のバージョンがインストールされます。
つまり、現在のexsample-package
の最新が1.3.5
の場合は1.3.5
がインストールされます。
yarn.lock
はpackage.json
と違いバージョン指定が正確に記載されているので、インストールされたバージョンが異なる場合はバージョンが変更され差分が発生します。
人によって1.2.3
がインストールされていたり1.3.5
がインストールされていたりするということは人によって利用しているバージョンが異なるということになります。
こういったパッケージのバージョン違いによる挙動の差異が発生することがあります。
yarn --frozen-lockfile
でyarn.lock
のバージョンをインストール
この挙動の差異をなくすために利用されるのがyarn --frozen-lockfile
です。このコマンドでパッケージの更新を行うとyarn.lock
に記載されているバージョンをもとに更新が行われるので環境によるバージョンの差異が発生しません。
CIなどでデプロイする際には未検証のバージョンが本番に混入しないために必須の設定となっています。
yarn ci
yarn --frozen-lockfile
と打てばよいのがわかっても、
yarn --frozen-lockfile
が長くて覚えにくくて打つのが面倒くさい問題というものが発生します。
その場合はpackage.json
に以下の記述をしておきましょう。
"scripts": {
"ci": "yarn --frozen-lockfile",
},
こうするとyarn ci
と打つだけでyarn --frozen-lockfile
と同じ更新方法が可能です。
ちなみにnpm
の場合は同様の機能がnpm ci
というコマンドで用意されているのでそこに準拠することで覚えやすいコマンド名になっています。
yarn.lock
のバージョンを更新していく運用方法
上記のyarn.lock
を更新せずに運用していくが割とディフェンシブな運用なのですが、yarn.lock
を更新しながらオフェンシブに運用していく方法もあります。
この運用の場合はyarn
などでyarn.lock
に更新が走った場合に更新情報をGit
にpush
してプロジェクトで最新のバージョンを共有します。
このままでは人によってバージョンが違う問題が発生してしまいますが以下のように起動時に最新になるように設定をしておけば古いバージョンを使い続けるという現象を減らすことができます。
"scripts": {
"dev": "yarn && yarn start"
}
ただ、package.json
の指定内で最新バージョンを使い続けることができる反面、検証が薄いバージョンが本番環境にリリースされたり、Gitのコンフリクトが発生しやすい名でデメリットも多く熟練されたチーム以外だと生産制が落ちることがあるので導入は慎重にする必要があります。
折衷案として起動コードを以下のようにしてyarn.lock
に更新頻度を下げるという方法もあります。
"scripts": {
"dev": "yarn --frozen-lockfile && yarn start"
}
これらを知らなくても問題になることは少ないのですがyarn
やnpm install
でパッケージを更新しているプロジェクトがあったら一度見直してみてよいかもしれませんね。
Discussion