16
$ npm install
my_module@0.0.1 /Users/antpaw/my_module
├── my_module@0.0.1 
└── UNMET PEER DEPENDENCY request@^2.74.0

npm WARN my_module@0.0.1 requires a peer of request@^2.74.0 but none was installed.

I don't understand how this can be only a warning. It's a pretty big deal for my app if "request" isn't install and my app will crash.

How can i make npm install exit with 1 if a peer dependency is unmet or is there something like npm do-i-have-everything-i-need-installed command that will exit with 1?

antpaw
  • 15,444
  • 11
  • 59
  • 88
  • Pretty much working as designed; if you want the dependency to be installed when your module is installed when use `dependency`. If you want to have consumers manage which version of `request` is installed, then you use `peerDependency`. It only takes two steps to install this way; rather that three if you fail the install... You'd probably be better off making a `dependency` to a major version: i.e. "2.x" that way it will get installed, but deduped on the consumer machine. closely related: http://stackoverflow.com/questions/35207380/how-to-install-npm-peer-dependencies-automatically – Meirion Hughes Aug 21 '16 at 17:40

2 Answers2

5

You are most likely using npm@3 (version 3).

As specified in the documentation, npm versions 1 and 2 used to install peerDependencies in most cases. Npm version 3 changes this behavior and no longer installs peerDependencies but instead throw a warning when the peerDependencies is not installed.

npm versions 1 and 2 will automatically install peerDependencies if they are not explicitly depended upon higher in the dependency tree. In the next major version of npm (npm@3), this will no longer be the case. You will receive a warning that the peerDependency is not installed instead.

The reasons behind the changes were mostly to avoid a dependencies hell when using peerDependencies or most of the time peerDependencies being used wrongly. There are a number of issues on the npm Github regarding peerDependencies like this one explaining some issues and what led to the solution to not install peerDependencies anymore.

If your application crashes if request is not installed, you are mostly requiring it. At the moment, in the npm environment, dependencies are packages you require(), devDependencies are packages you require() only for development, tests, etc.

peerDependencies were originally designed to address problems with packages that were mostly 'plugins' for other frameworks or libraries, designed to be used with another 'host' package even though they're not directly using or requiring the 'host' package.

For example, Grunt plugins are meant to be used with Grunt but never require('grunt');. Adding grunt as a dependencies would lead to a new downloaded copy of the package that would never be used. Even if some plugins have direct dependencies to the 'host' package and specify the 'host' package in the dependencies, that would lead to multiple copies of the 'host' package.

A peerDependencies is a way of saying that a package works when plugged in a version of an 'host' package, so if you install this package, you should also install this other package manually.

That's the behaviour you're currently having, you're installing your application, listing request as a peerDependencies, so you should install it for it to work and remove the warning, otherwise, you'll need to move to a classic dependencies.

HiDeoo
  • 10,353
  • 8
  • 47
  • 47
  • 1
    "A peerDependencies is a way of saying that a package works when plugged in a version of an 'host' package". Exactly. So my question is still: how this can be a warning? NPM knows that my host package is broken and warns me about that (with exit 0)? – antpaw Aug 22 '16 at 12:21
  • 1
    The *current* point of `peerDependencies` is now to let the end-user managing it and installing it to avoid a dependencies hell. It will only warn you if the `peerDependencies` is missing and that you should install it, it'll not be done for you. The only way to get an automatic installation is to move away from `peerDependencies`. – HiDeoo Aug 22 '16 at 12:30
  • it's a great point, the problem is the execution of that point. I don't want automatic installation via `dependecies` because i could end up with two or more different versions of the same module installed, which would be really bad is my usecase (there are a lot of usecase where this is not an issue). That's why I'm using `peerDependencies`. "... is missing and that you should install it..." How is "something-I-should-do" a warning, it doesn't make any sense to me? – antpaw Aug 22 '16 at 13:10
  • My answer is mostly based around explaining the new behaviour and why at the moment you can't avoid it. I'm not saying that's the change is a good thing, or the warning-only is a good choice (that's not even something that should be discussed on SO but more on their GH). The one (of many) issue I linked is a perfect example why it helps but it's not perfect at all yet. The only bad "workaround" I've found for this use case and to also support npm@2 and npm@3 is to dupe all `peerDependencies` as `dependencies` and run in a post install hook a [`npm dedupe`](https://docs.npmjs.com/cli/dedupe). – HiDeoo Aug 22 '16 at 13:35
  • Okay I understand your intentions now. But I still think it's either the package is needed, so it has to be installed, or the package is not needed, so why would it be declared as any kind of dependency then? – antpaw Aug 22 '16 at 13:57
  • This has to be one of the best explanations of peerDeps that I have ever read. – Shanimal Dec 16 '19 at 18:03
3

It looks like I've found a way to exit with 1, after/before (I think the order doesn't matter) doing the general npm install I need to run npm install my_module which will exit with 1. That means I can define a list of modules I want to make sure to have exactly what they need (defined in peerDependencies) in my CI script, not pretty but it's better than nothing.

So npm install doesn't break no matter what kind of dependencies nonsense you will define in your package.json. npm install module_name will break if you have nonsense in your package.json.

antpaw
  • 15,444
  • 11
  • 59
  • 88