yarn.lockについて理解する

# 目次
1. yarn.lockとは
2. yarn.lockファイルの見方
    2.1 Dependency Name
    2.2. Resolved Version
    2.3 Installation URL
    2.4 Integrity Hash
    2.5 Package Dependencies
3. 依存関係グラフの視覚化方法
4. yarn.lockを手動で修正する必要性
5. yarn.lockを再生成する必要性
6. 参考

# 1. yarn.lockとは
https://classic.yarnpkg.com/lang/en/docs/yarn-lock/

>Yarnは、それぞれの依存関係がどのバージョンでインストールされたかを正確に保存する必要があります。
Yarnは、プロジェクトのルートにあるyarn.lockファイルを使います。
インストール中、Yarnはトップレベルのyarn.lockファイルのみを使用し、依存関係内に存在するyarn.lockファイルは無視します。
トップレベルのyarn.lockファイルには、依存関係ツリー全体のすべてのパッケージのバージョンをロックするためにYarnが必要とするすべてのものが含まれています。
すべてのyarn.lockファイルはソース管理にチェックインする必要があります。
これにより、Yarnは同僚のラップトップであろうとCIサーバーであろうと、すべてのマシンに同じ正確な依存関係ツリーをインストールすることができます。

以下の記事を参考にしてまとめていきます。
[The Ultimate Guide to yarn.lock Lockfiles](https://www.arahansen.com/the-ultimate-guide-to-yarn-lock-lockfiles/)

# 2. yarn.lockファイルの見方

yarn.lockロックファイルは、プロジェクトの依存関係だけでなく、その推移的依存関係も記述します。
yarn.lockのすべてのエントリは、平坦化されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/b4ced061-d75f-6492-4f90-26ba986c2d80.png)
[引用](https://www.arahansen.com/content/images/2022/02/Group-1--5-.png)

## 2.1 Dependency Name
プロジェクトのpackage.jsonまたはプロジェクトの依存関係のpackage.jsonのいずれかで定義されている依存関係の名前と要求されたバージョンです。

同じパッケージの複数のバージョンが異なるpacakge.jsonファイルで要求されている場合、この行には複数のエントリが含まれることがあります。

以下が例です。
Aというパッケージが@babel/code-frame@^7.0.0、
Bというパッケージが@babel/code-frame@^7.12.13、
Cというパッケージが@babel/code-frame@^7.22.13に依存するとします。
この場合、yarn.lockファイルは次のようなものを生成します：

```yarn.lock
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13":
  version "7.22.13"
  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
  integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==
  dependencies:
    "@babel/highlight" "^7.22.13"
    chalk "^2.4.2"
```
Dependency Name以降は全く同じです。
これはyarnが、"これらの依存関係はどちらも、実際にはこの依存関係の同じバージョンを使うことができる"と解決しているからです。

複数の依存関係のバージョンが意味的に同じである限り、解決された依存関係を共有できるということです。

## 2.2. Resolved Version
- 依存関係が実際にインストールされたバージョンです。
- yarn.lockが生成される前に、これはpackage.jsonのセマンティックバージョニングルールによって決定されます。
- 実際にインストールされたバージョンが依存関係名で指定された番号と異なる可能性があります。

## 2.3 Installation URL
- yarnが依存関係を取得するために使用するURLです。
- デフォルトではregistry.yarnpkg.comを使用します。
- 以下二つの方法で別のyarnレジストリを指定することもできます。
    - --registry CLIフラグ
    - .yarnrcファイルにレジストリ<registry_url>を定義
- npmレジストリにあるパッケージはすべてyarnレジストリからもインストールできます

## 2.4 Integrity Hash
- プロジェクトのセキュリティにとって重要です。
- yarn.lockファイルの生成の一部として、yarnはダウンロードされたコンテンツに基づいて、各依存関係のインストール用のハッシュ値を計算します。次にその依存関係をダウンロードすると、yarnは再びハッシュを生成します。
- 新しい値とyarn.lockに保存された値の間に不一致がある場合、yarnは次のようなエラーを投げてインストール全体が中止されます。
    ```terminal
        Integrity check failed for <package-name> (computed integrity 
        doesn't match our records, got "<integrity-hash-value>")
    ```
- yarnはインストールURLを見て、ファイルの中身をダウンロードし、ハッシュを生成します。ファイルの中身が全く同じ場合はハッシュ値は同じ値になります。
- yarnは悪意のあるコードでハイジャックされたライブラリ（バージョンは変更せず、内部に悪意のあるコードを埋め込む等）をインストールするのを防ぎます。

### 整合性チェックの失敗を修正する方法
- 最も重要な最初のステップは、依存関係がまだ安全に使えることを確認することです。
- 最善の方法は、プロジェクトがホストされている場所（GitHubなど）をチェックして、他の人が同じ問題を見ていないかどうかを確認することです。
- ライブラリがまだ安全であることを確認したら依存関係をアンインストールし、再インストールします。

## 2.5 Package Dependencies
- パッケージが正しく動作するために利用可能でなければならない依存関係のリストです。
- 依存関係をできるだけ共有し、コードの重複を避けたいので、これは重要です。

# 3. 依存関係グラフの視覚化方法
```terminal
yarn why <package> 
```
依存関係ツリーの内訳を知ることができます。

以下を例にします。
```terminal
$ yarn why copy-descriptor
yarn why v1.22.19
[1/4] 🤔  Why do we have the module "copy-descriptor"...?
[2/4] 🚚  Initialising dependency graph...
[3/4] 🔍  Finding dependency...
[4/4] 🚡  Calculating file sizes...
=> Found "copy-descriptor@0.1.1"
info Reasons this module exists
   - "anymatch#micromatch#snapdragon#base#class-utils#static-extend#object-copy" depends on it
   - Hoisted from "anymatch#micromatch#snapdragon#base#class-utils#static-extend#object-copy#copy-descriptor"
info Disk size without dependencies: "12KB"
info Disk size with unique dependencies: "12KB"
info Disk size with transitive dependencies: "12KB"
info Number of shared dependencies: 0
✨  Done in 0.26s.
```
info Reasons this module existsを見ると
以下の順で依存関係にあるのが分かります。
anymatch→micromatch→snapdragon→base→class-utils→static-extend→object-copy→copy-descriptor

# 4. yarn.lockを手動で修正する必要性
ありません。
- lockファイルは生成されたファイルで、すべてyarnによって管理されます。
- 内容を自分で編集しようとすると、ロックファイルを無効にしてインストールに失敗する危険性があります。
- また、整合性ハッシュ値（Integrity Hash）を間違った値に変更すると、依存関係が間違って変更されたとyarnが判断してエラーを投げる可能性があります。
- lockファイルでマージの衝突があった場合もyarnが自動的に修正してくれます。

# yarn.lockのマージの衝突を修正する方法
次の手順で修正して下さい。
1. package.jsonのコンフリクトを手動で修正する
2. yarn install を実行します。
    yarnはpackage.jsonで行われた修正を受け取り、ロックファイルがpackage.jsonファイルの状態を反映するようにコンフリクトを解決する正しい方法を決定します。

# 5. yarn.lockを再生成する必要性
yarn.lockを再生成しないべきです。

仮にyarn.lockを再生成するならば
正確なバージョンを使った（例：^, ~を使わない）package.jsonを通してのみ更新することで、依存関係の更新を明確にするべきです。
こうすることで、ロックファイルを再生成しても、同じバージョンの依存関係がインストールされるようになります。

# 6. 参考
- [package-lock.jsonとyarn.lockの存在理由](https://zenn.dev/luvmini511/articles/56bf98f0d398a5)
- [The Ultimate Guide to yarn.lock Lockfiles](https://www.arahansen.com/the-ultimate-guide-to-yarn-lock-lockfiles/)

# 参考記事を書いてくださった皆さまに感謝致します！