question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Lerna should ignore peer/dev dependencies of symlinked packages.

See original GitHub issue

Repro 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:closed
  • Created 3 years ago
  • Reactions:19
  • Comments:6

github_iconTop GitHub Comments

5reactions
heygradycommented, Jun 12, 2020

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.

// obviously dreaming; in the repo-level package.json
{
  // conceptually similar to defining a "resolutions" in every workspace package
  // would install these in the repo-level node_modules folder _only_
  "singletonDependencies": {
    "react": "*", 
    "react-dom": "*",
    "react-router": "*",
  }
}
1reaction
Xiliscommented, Jul 4, 2020

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 includes react and react-dom as peer/devDependencies, not prod dependencies. Bootstraping the monorepo symlinks ./packages/components to ./packages/frontend/node_modules. When the import * as react from 'react'; is executed (inside components), 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

Read more comments on GitHub >

github_iconTop Results From Across the Web

Shell lerna peer dependencies | Learn-codes.net
Make plugin a peer dependency of eslint-config package, and entrust package manager to ... Lerna should ignore peer/dev dependencies of symlinked packages.
Read more >
npm set peer dependency versions Code Example - Code Grepper
Answers related to “npm set peer dependency versions” ... Your requirements could not be resolved to an installable set of packages. league/omnipay v3.0.0 ......
Read more >
npm7.0源码分析(二)之npm install执行逻辑 - 掘金
load () { // we don't need to load package-lock.json except for top ... otherwise prefer package-lock // and ignore npm-shrinkwrap if both ......
Read more >
https://koji.mbox.centos.org/pkgs/work/tasks/4932/...
tools/node-lint-md-cli-rollup/package-lock.json . ... test/fixtures/module-require-symlink/node_modules/dep1/node_modules/bar/index.js .
Read more >
Half-Life: A Place in the West update for 29 October 2019 · SteamDB
... Removed – resources/app/node_modules/yauzl/package.json (1.52 KiB) ... resources/app/node_modules/smooth-scrollbar/src/render/will-overscroll.js (821 B) ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found