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.

Transitive dependencies (peer dependencies are not linked by lerna)

See original GitHub issue

Hello!

First of all, thank you for this great tool and your hard work.

However, I’ve encountered a problem, which I cannot find a way to untangle without using some nasty workarounds.

I have a monorepo with several packages, some packages are components, which I’m building using other packages. I’ve pictured all the important dependencies on the following image:

deps-scheme

Rectangles are my local packages, ovals are third-party dependencies. Arrows show dependencies. Dashed arrow is a peer dependency.

The Component Package is a package I’m trying to build.

The Bundler is our internal build tool. It’s an orchestrator like Gulp or something.

Bundler is using a Build Scenario to run Rollup Processor and compile the source code in the Component Package. However, the Rollup’s configuration file as well as plugins configuration is stored inside of a Build Scenario package, which depends on License Plugin.

The License Plugin requires the Rollup under the hood in order to check it’s version. So, it’s a peer dependency for it. I’ve marked it with a dashed arrow in the image.

The Rollup Processor is a package which actually depends on the Rollup (which it executes).

When normal npm install is done inside of the Component Package, all dependencies are properly installed, i.e.: Component > Scenario > Processor > Rollup. So when License Plugin is trying to load the Rollup it gets the installed version correctly.

The problem arises with lerna linking. When lerna links all the packages, the License Plugin doesn’t get a link to the Rollup, because it doesn’t depend on it directly, but only transitively through a peer dependency.

In the end, I can’t build the Component Package, because the License Plugin couldn’t find a Rollup dependency.

Take notice, that I can’t make Rollup a dependency of the Scenario, because the scenario doesn’t care about an actual rollup version to use. It is controlled by the processor.

I think that lerna linking should take peer dependencies into account and try to link to them through the dependencies of the parent packages. In my example, it should see that License Plugin is using Rollup as a peer dependency and it should start looking for a package to link by resolving dependency chains from it’s parent Build Scenario.

I know it looks complicated, but it’s a viable use case and it should be implemented in order to make such transitive dependency schemes work.

The “hoisting” feature could help here, but it’s too aggressive in my opinion and it has its own problems.

What do you think?

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:7
  • Comments:12 (4 by maintainers)

github_iconTop GitHub Comments

15reactions
evocateurcommented, Jan 31, 2019

Actually, what yarn is doing is installing almost everything in the root node_modules, which is resolved correctly when scripts run from the various leaf nodes.

Generally speaking, a package specified in peerDependencies should also be specified in devDependencies. That’s how the pattern works for “traditional” npm packages, and in a monorepo it’s best to just install those peers in the root and let the node module resolution algorithm do the work.

The best practice for monorepos, in my opinion, is to run all dev scripts from the root, not the leaf nodes. It helps reduce repetition, is often times faster, and avoids weird bugs like this.

4reactions
slavafomincommented, Feb 9, 2019

@evocateur why are you closing this issue? It’s a legitimate problem. Your advice on “Just install the license plugin in the root” is a dirty workaround and not a proper solution.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Implicit transitive peer dependencies - DEV Community ‍ ‍
You won't "implicitly inherit" the peer dependencies declared in Foo . Peer dependencies are a fickle beast.
Read more >
node.js - Interdependencies between two lerna monorepos
I'm having two monorepos which I want to develop simultaneously. Here's the structure: Monorepo A package.json lerna.json packages/ ...
Read more >
lerna add - Fig.io
--exclude-dependents, Exclude all transitive dependents when running a command with --since, overriding the default 'changed' algorithm ; --include-dependents ...
Read more >
Monorepo Maintenance and Development with Rush
A transitive dependency is any dependency in the dependency tree that is pulled in by direct dependencies and is not specified as a...
Read more >
Should you Pin your JavaScript Dependencies?
By "automatically", we mean that any time you run npm install you will get the very latest version matching your SemVer - assuming...
Read more >

github_iconTop Related Medium Post

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