yarn
yarn copied to clipboard
yarn link uses peerDependencies from wrong node_modules
Bug description
Yarn link/install follows devDependencies
of linked package in linked package modules. Same happens for file
if not pointed to the compiled dependency.
Command
yarn link
yarn install
What is the current behavior?
When you create two projects, say, a react library react-lib
, and in the same repo you want to use it in other react application react-app
, and link the react-lib
to react-app
, yarn somehow uses packages specified in peerDependencies
from devDependencies
of react-lib
to components from react-libs
instead of the packages from react-app
.
Furthermore, packages from react-app
correctly use their own dependencies.
This does not happen, if i use file
and point to the dist
directory instead of link
. However, then I loose ability to work on the library without running yarn install --force
each time i make a change in the library.
It does not matter if one uses:
cd react-lib
yarn link
cd ../react-app
yarn link react-lib
or adds entry in package.json
:
"react-lib": "link:../react-lib",
What is the expected behavior?
devDependencies
should not be linked/exported, peerDependencies
should be loaded from react-app
node_modules
.
Steps to Reproduce Clone this repo: https://github.com/Wunsz/yarn-link-problem
Run:
cd yarn-link-problem/react-lib
yarn install
yarn start
after that, in the other terminal
cd yarn-link-problem/react-app
yarn install
yarn start
You will see a blue Material UI
button. However, in react-app
, a theme is specified that should make this button green. If one changes link:../react-lib
to 'file:../react-lib/dist` and reruns above process, the button will be green.
Note that one has to specify the compiled dist
directory! Otherwise same as above happens an the button is blue.
Furthermore, Material UI Core module in react-lib
and react-app
are different.
Note
This applies to every package specified in peerDependencies
and devDependencies
. For react, the workaround was to remove react
and react-dom
and add @types/react
and @types/react-dom
. If this is not done, react will throw errors about multiple versions of react.
Environment
- Node Version:
14.0.0
- Yarn v1 Version:
1.22.4
- OS and version: Ubuntu 18.04
for those wondering; I ran into the same issue and used yalc to fix my problem.
This is an issue that seems like it will continue to get worse over time as native module loading becomes the norm. FWIW — you can have some success using moduleNameMapper
to force jest to perform explicit lookups, but ultimately you end up being responsible for dependency hell.
I think @driescroons suggestion to use a tool like yalc that actually hard-copies your linked dependencies is currently the only viable solution for large/mid scale projects
I think I'm restating what's already been said here but here's my take on what I'm experiencing I'm working on an app and I have a package that I'm yarn linking in to the app.
- run
yarn link
inmyPackage
- run
yarn link "myPackage"
inmyApp
... -
myPackage
specifiessomePackage
as apeerDependency
inmyPackage/package.json
- sosomePackage
will not be installed bymyPackage
because it expects it to be installed by its parent (myApp
in this case). -
myApp
specifiessomePackage
as adependency
inmyApp/package.json
The dependency in myApp
should satisfy the peerDependency
in myPackage
but instead the module is not found. Presumably, as is originally stated in this issue, because it's referencing the devDependencies in myPackage/node_modules
instead of myApp/nodeModules
That seems broken 🤔
I shouldn't have to install somePackage
as a dependency in myApp
, right?
update: yalc worked for me 🙂. Thanks @driescroons
I had a similar issue where adding a package via yarn link
to a project would break unrelated things (whereas the two projects worked fine on their own, or if I'd use the package without yarn link
).
I think it's because the linked package's dependencies will take priority (this issue) and they used different versions than my main app's dependencies. I.e. I had "typescript": "^4.2.3"
in my main app but "typescript": "^4.6.3"
in the linked package. The ^
would allow my main app to resolve this dependency to the version in the linked package, breaking typescript in the main app. This was confusing because there was no change in the main project's yarn.lock
that would indicate that the typescript
version changed.
I got around this by having exact dependencies in the main project. I.e. "typescript": "4.2.3"
. I don't think this solves the root cause but it makes sure I know exactly which dependency is loaded, in which case I don't care where it is loaded from.
I encountered the same problem today, when updating to React 18 (probably was there before, just hadn't notice).
I have a component library with peer dependencies and an example app in the same repo. The package.json
in the subfolder called example
references the component library like this: component-library: "../"
.
I get errors saying the example app uses multiple versions of React and styled-components, even thou they are only peer (and dev) dependencies in the library. If I delete node_modules
in the library, the example app stops working, with error messages pointing to the library's deleted node_modules
.
I had react
and react-dom
in devDependencies
(for some reason), I removed them (keeping @types/react(-dom)
) and now it works. However, I still need styled-components
as the typings are included in the bundle in that case.
Not sure if there is something I'm doing wrong, but I would expect the example app to resolve modules from the local node_modules
instead of the library's node_modules
.
I'm not sure how much of yarn
is built on top of npm
, but I reported a similar NPM issue today: https://github.com/npm/cli/issues/7171
As a vite user that also hit this problem, I've had some success using dedupe in the vite.config.js (e.g. resolve: { dedupe: [ 'dependency-name', ...] }
) to workaround it. It forces the build to use the dependency from top-level app's node_modules.