This repo is a proof of concept that proves an issue we have found in yarn workspaces.
To replicate you need:
-
Two workspaces with each depending on the same two dependencies We'll call these the "root" dependency and the "child" dependency
-
The "child" dependency needs to declare a peer dependency to the "root" dependency
-
The two workspaces require different versions of the "root" dependency
-
Both workspaces require the same version of the "child" dependency
-
The "child" dependency has been
nohoist
edIf it wasn't it would resolve the "root" dependency from the top level
node_modules
instead of the version declared in the workspacespackage.json
In this repo we have replicated as:
-
workspace-a
requiresmobx@4.0.0
andmobx-react@5.1.2
-
workspace-b
requiresmobx@4.3.0
andmobx-react@5.1.2
-
mobx-react
requiresmobx@^4
as a peer -
The root
package.json
hasnohoist: [ "**/mobx-react" ]
When resolving dependencies yarn will only build the dependency tree for the same version of a dependency once. So when it resolves the "child" it does so in the context of the first workspace. The dependency graph for the "child" then gets locked with the version that the first workspace has declared and resolved for the "root" dependency.
When resolving the same version of the "child" for other workspaces yarn ignores that the version required of the "root" is different and so the "child" gets installed with the first workspaces version of the "root".
This results in:
node_modules > root 1.0.0
workspace-a > node_modules > child 1.0.0
workspace-b > node_modules > root 2.0.0
workspace-b > node_modules > child 1.0.0
workspace-b > node_modules > child > node_modules > root 1.0.0
The end result is that when code from the "child" runs in workspace-b it will be using a different version of "root" than the one that workspace-b is requesting, despite that version being correct for it's dependency string.
Checkout this repo and run:
yarn install --force --check-files
./listVersions.sh
you will see that mobx-react
inside workspace-b
has the wrong version of
mobx
installed inside it.