pnpm: Problem with peer dependencies when using `pnpm link`
When a package that has peer dependencies is linked to some destination, the node_modules
of that package are included in the symbolic link. This causes the dependencies of the package to come from another source than the destination’s node_modules/.pnpm
folder. This becomes a problem with peer dependencies, because they end up not pointing to the same exact file. Even when the version on both side is an exact match, this can lead to problems when exact references (e.g.: singleton) are needed.
The simple example is for a React package, where React is marked as a peer dependency. When a consumer package links the first library, there will be a missing in the imported files, leading to countless problem on runtime.
pnpm version:
8.6.3
Code to reproduce the issue:
I’ve created a reproduction repository that includes a README.md
file with all the instructions needed in order to get a better feel of the issue.
https://github.com/kevinpastor/pnpm-link-peers-issue
Expected behavior:
When linking a package that has peer dependencies to some destination, we should expect that the peer dependencies are respected.
Actual behavior:
The peer dependencies of the package behave more like dependencies. The peer dependencies are consumed from the package’s original location and not from the destination’s node_modules
.
Additional information:
node -v
prints: v18.16.0- Windows, macOS, or Linux?: Windows
- Organization discussion
About this issue
- Original URL
- State: open
- Created a year ago
- Reactions: 5
- Comments: 16 (6 by maintainers)
I know, we need better docs. The most upvoted issue is actually related to linking: https://github.com/pnpm/pnpm/issues/4640
Dependencies added via the
file:
protocol are already hard linked. So if you edit a file, it will be changed in the consumer. But if you build your package, then the files in dist are probably replaced, so it doesn’t matter that they were hard links.You cannot solve this with
pnpm link
. What you can do is use afile:
protocol. If it is inside a workspace, you could also use injected dependencies.In your case, if you need this for local development and the projects are in separate directories, probably the
file:
protocol would be the way. You can put it into an override like so: