npm Community Forum (Archive)

The npm community forum has been discontinued.

To discuss usage of npm, visit the GitHub Support Community.

What is the current state of peer dependencies in npm?

Howdy folks :wave:

I’ve just built a thing that feels like it needs a peer dependency (for the first time in like 7 years working with node!) but I’m wondering if there is any guidance on if we should be using peer dependancies in 2018? :thinking:

In the main documentation, it mentions “In the next major version of npm (npm@3)” and that is a little bit out of date now :joy: especially because of the overhaul that came in npm@5

Any guidance would be appreciated :tada:

In the post npm@3 world:

peerDependencies are assertions that result in warnings if they fail. So a pretty soft assertion. They instruct folks to install the missing peer dep, but make no attempt to install it themselves.

There is one lingering issue relating to them, as this assertion framework is a little brittle: If your applciation depends on library A which depends in turn depends on B and C. And C has a peer dep on B. It’s possible for B to get installed under A, but C installed at top level, resulting in an unresolved peer dep when it otherwise should be resolved.

I have some thoughts on how we can address this, but it will require some deep changes to how we resolve module trees and so is scheduled for post npm@7 (so, end of this year, probably).

In the meantime, authors of module A can ensure this doesn’t happen by shipping an npm-shrinkwrap.json or by bundling B and C.

One problem I have with peerDependencies that sometimes you want to surpress warnings about peerDependencies. The effects of this are:

Now all these examples could be solved if all the packages were architected in a different way, but unfortunately it’s not the reality.

An example of a package that does not use peerDependencies because most warnings would be irrelevant is Sequelize

If the DB adapters had peerDeps on Sequelize, why would there be extraneous warnings? Do folks use the DB adapters independently of Sequalize?

It’s the other way around, Sequelize needs one of the low-level DB adapters to be installed (e.g. pg, mysql2, …). Yes, they are not Sequelize-specific. If Sequelize had peerDependencies on all of these, you would only ever satisfy one of them.

Now as said, this could be solved if Sequelize had independent packages that acted as a bridge between Sequelize and the adapters, and you provide an instance of one of these bridges to the core. But that would entail a lot of refactoring, problems with versioning and testing, etc that the Sequelize team chose not to deal with. This is the unfortunate reality with many packages.

Ah, ok, gotcha. I don’t think peerDependencies are an appropriate tool for that class of problems. The one thing their good for is letting plugins depend on the version of the thing they plug into.

It does point to a need for another kind of assertion or constraint, but I don’t think that it should be peerDependencies.

It may be that we need some kind of more general assertion system. Relatedly: folks would like some way to declare something only working as a singleton.

I think I need to see this as a graph to follow :joy: But essentially you’re talking about deep peer dependencies (not quite the same as the diamond require issue but I put it in the same mental bucket).

My particular use case is very “top level” and I’m pretty sure this won’t be a problem.

My take away is this: It’s cool to use peer dependencies now but just be aware of what you’re doing.

I was going to ask if we should update the documentation but it sounds like the overhaul is in the roadmap and I assume it will get updated then :+1:

Thanks for the help folks :tada:

We absolutely should update the docs. :stuck_out_tongue_closed_eyes: You’re right though, left to our own devices we likely won’t do so till an overhaul. I would happily take a PR though!

And as you say, it is on the roadmap, albeit a bit in passing:

Two-pass installer where resolution of the logical tree is distinct from computing the physical tree. With this we may be able to, at long last, end the pain around peerDependencies.