yarn workspacesのnoHoistがうまくされないときあるいはnoHoist設定の罠

yarn workspacesでmonorepoを構成しているときに特定のpackageだけhoistの対象外にしたいというときがある。

そういうときにどうすればよいかというと、noHoistオプションを単に使えばいいのだけどなぜかちゃんと書いてあるつもりなのにnoHoistが効かなくて困り果ててしまうケースがある。

このnoHoist設定は実はめちゃくちゃややこしく罠しかないので覚書として書いておく。

nohoist in Workspaces | Yarn Blog

結論から

noHoistにはディレクトリパスではなくパッケージ名のglobを書かねばならない

です。

それでは順を追って見ていきましょう。

packageの名は

こういうmonorepo構成だったとする。このうちfun-utilsだけはhoistの対象にしたくないのでnoHoistしたいとする。

.
├─package.json
└─packages
  ├─fun-domain
  ├─fun-interfaces
  └─fun-utils // hoistしてほしくない

そしてpackages/fun-utilspackage.jsonはどうなっているかというとこう。

{
  "name": "smile-utils",
  "version": "1.0.0",

  "dependencies": {
    "cross-env": "5.0.5"
  }
}

おや?ディレクトリはpackages/fun-utilsなのにpackgae.jsonnameフィールドは「smile-utils」ですね。

でもまあpackagesのフィールドはディレクトリなわけだし、普通こう書いてしまいますね。

"workspaces": {
  "packages": ["packages/*"],
  "nohoist": ["**/fun-utils", "**/fun-utils/**"]
}

noHoistにディレクトリ名ベースのglobを書いた

ただこれではnoHoistの対象になりません

どうすればよいか。

"workspaces": {
  "packages": ["packages/*"],
  "nohoist": ["**/smile-utils", "**/smile-utils/**"]
}

nameフィールドのglobに変えた

noHoistは実はpackage.jsonnameのglobにしないといけなかったのです……。

ちなみに

1度rootで yarn install してあり、すでに各パッケージにlockファイルとnode_modules存在する状態からnoHoistの指定する場合は、noHoist対象node_modulesyarn.lockを削除しておかないといけないことを確認しています(v1.22.4)

yarn install --force でもダメなので注意しましょう……。


😇