Lerna should ignore peer/dev dependencies of symlinked packages.
See original GitHub issueRepro for this here: https://github.com/dwjohnston/lerna-react-monorepo
Expected Behavior
If a have package a with:
"devDependencies"
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
"peerDependencies": {
"react": "^16.13.1",
"react-dom": "^16.13.1"
}
and package-b depends on package a:
"dependencies" : {
"package-a": "..."
}
Then I don’t want package-b to have access to the react
and react-dom
modules in package-a’s node_modules.
Current Behavior
package-b, when importing the code from package-a, will resolve react
to the react
module in package-a’s node-modules.
This causes this common error: https://github.com/facebook/react/issues/14257#issuecomment-508808246
The work around to this, is to hoist all dev dependencies (ie. lerna link convert
). Where this would potentially be problematic is if you had different versions of a dev dep in different packages and so it wouldn’t be hoisted.
Alternative solution is to use webpack aliasing.
Possible Solution
Either by default, or provide a ‘don’t symlink peer dependencies’ option.
Surely this is fairly feasible - at the symlink step, first check any for any peer dependencies, and don’t symlink those.
This does sound like though - that you would not be symlinking the whole folder and instead be symlinking individual folders in the node_modules folder. Which I think this issue is suggesting: https://github.com/lerna/lerna/issues/1321
Is it possible to exclude folders from a symlink?
lerna.json
<!-- Please paste your `lerna.json` here -->
lerna-debug.log
<!-- If you have a `lerna-debug.log` available, please paste it here -->
<!-- Otherwise, feel free to delete this <details> block -->
Context
Trying to create a basic react monorepo where you have
packages/
app1/
app2/
common-react-components/
And you run into this ‘two different versions of react’ issue.
Your Environment
See repro - Have been trying with both npm and yarn.
Executable | Version |
---|---|
lerna --version |
VERSION |
npm --version |
VERSION |
yarn --version |
VERSION |
node --version |
VERSION |
OS | Version |
---|---|
NAME | VERSION |
Issue Analytics
- State:
- Created 3 years ago
- Reactions:19
- Comments:6
Top GitHub Comments
We are fighting similar issues on our app. It is common in react packages to have singleton context objects, which breaks when the package is resolved to multiple places in the filesystem. In particular,
react-router
is very sensitive to this. Any package that dealt with react context singletons might be caught in the trap.Two sibling workspace packages cannot share certain singleton-reliant dependencies during development mode, and may have problems during final build if you are using webpack.
We landed on moving those “there shall be only one” deps out of the app (there were only a few that affected dev) to the repo-level
package.json
, which at least helped ensure that we were always getting the same one.There does not seem to be a workspace setting for “please, oh please, ensure that only one copy of this package exits in the entire repo”.
That feature is desirable for local development or for bundling an app to be deployed. Currently there is no way (AFAIK) to ensure only one single copy of a dependency is installed; even with the same version number in every workspace package.
Ultimately this feels like a missing yarn workspaces feature.
Facing similar issues: a lerna, typescript monorepo that includes a nextjs/typescript frontend app -
frontend
, a nodejs/typescript backend app -backend
, and a react/typescript shared components package -components
(for other todo frontend apps).The
components
package includesreact
andreact-dom
as peer/devDependencies, not prod dependencies. Bootstraping the monorepo symlinks./packages/components
to./packages/frontend/node_modules
. When theimport * as react from 'react';
is executed (insidecomponents
), the “multiple instances of react” is triggered, as it gets resolved into./packages/components/node_modules/react
, and not into./packages/frontend/node_modules/react
.I have another “question” or something I’d like to confirm; if my understanding around lerna is correct based on comments from the maintainer in other github issues, lerna (at least the bootstraping part) should practically not be used in CI steps, thus the “shared packages” should be published either way for production (in which case the “multiple instances of react” would not happen as there would only be a single
react
dependency.In the example above, we would dockerize the frontend and backend seperately, and seperate the dockerization into multiple stages / intermediate images (so in one step/image install devDependencies and build/compile the package, in another step install only production dependencies and copy over the compiled code from the previous step). Publishing the
components
package makes this straight forward, I’m just wondering if there is some “best practice” usage that uses lerna and does not require publishing.Related issue: https://github.com/facebook/react/issues/13991