yarnでworkspaceを使用した際のモジュールの格納位置について調べてみました。
一部のモジュールが、何故かワークスペースのルートに配置されず、それに依存しているモジュールでエラーが発生したためです。
調査方法
以下のような構成のプロジェクトを作成し、依存するバージョンを適宜変更して、ワークスペースのルートでyarn installを実行しました。
yarn-workspace-test
│ package.json
│
├─first
│ │ package.json
│ │
│ └─src
│ index.ts
│
├─second
│ │ package.json
│ │
│ └─src
│ index.ts
│
└─third
package.json
ワークスペースのpackage.json
{
"name": "yarn-workspace-test",
"version": "0.0.1",
"private": true,
"scripts": {
"build": "yarn workspaces run build",
"lint": "yarn workspaces run lint"
},
"workspaces": [
"first",
"second",
"third"
]
}
個別プロジェクトのpackage.json
{
"name": "first",
"version": "0.0.1",
"description": "",
"license": "ISC",
"author": "",
"devDependencies": {
"eslint": "6.7.2"
}
}
通常時
全プロジェクトで同一バージョン
node_modulesの場所 | 指定バージョン | 配置バージョン |
---|---|---|
first | 6.7.2 | ./binのみ |
second | 6.7.2 | ./binのみ |
third | 6.7.2 | ./binのみ |
ルート | - | 6.7.2 |
モジュールはルートのみに配置されたが、各プロジェクトにも、.bin以下は作成された。
コンフリクト有
全プロジェクトで異なるバージョン
node_modulesの場所 | 指定バージョン | 配置バージョン |
---|---|---|
first | 6.7.0 | ./binのみ |
second | 6.7.1 | 6.7.1 |
third | 6.7.2 | 6.7.2 |
ルート | - | 6.7.0 |
6.7.0がルートに配置された。それに対応する、firstにはモジュールが配置されなかったが、secondとthirdにはそれぞれ指定のバージョンが配置された。
コンフリクト有(1対2)
1プロジェクトのみを異なるバージョン | node_modulesの場所 | 指定バージョン | 配置バージョン |
---|---|---|---|
first | 6.7.0 | 6.7.0 | |
second | 6.7.2 | ./binのみ | |
third | 6.7.2 | ./binのみ | |
ルート | - | 6.7.2 |
2プロジェクトで指定されているバージョンがルートに配置された。
想定
公式ドキュメントでは、衝突解決のルールが見つからなかったが、おそらく以下のようなルールになっている。
バージョンに矛盾がある場合には、その中ので最も使用されているバージョンをルートのnode_modulesに配置。それ以外は、そのバージョンが使用されているプロジェクトのnode_modulesに配置。使用回数が同じ場合には、最も小さいバージョンをルートに配置。
動作する理由
上記のルールで配置すれば、ほぼ問題は発生しない。
yarnコマンドの実行時のノードモジュールの検索は、自プロジェクトのnode_modulesを最優先に、上位ディレクトリにあるnode_modulesを順に見ていくため。