--only=prod Incorrectly Applied When Installing Specific Packages

What I Wanted to Do

I wanted to install a package, add it to my devDependencies list, and install only the production dependencies of the package in question.

What Happened Instead

npm installed nothing.

Reproduction Steps

Run this command from a directory with a package.json file that has no dependencies of any kind listed:

npm install jquery --only=prod --save-dev

Details

I am explicitly telling npm that I want jquery installed, but the above command just adds jquery to my package.json devDependencies list, and installs nothing.

I would expect the --only=prod flag to be applied to the specific packages I’m installing (here, jquery). Instead, npm appears to be applying --only=prod to my project’s package.json file as if I were running install without specifying a package to install.

The command I passed should be interpreted as: “Install jQuery and only jQuery’s production dependencies, then add jQuery to my project’s development dependency list.”

npm is currently interpreting this command as: “Add jQuery to the project’s development dependency list, then install only the production dependencies of the project.” This is an incorrect interpretation because I have EXPLICITLY told npm that I want jQuery installed. It’s as if npm is completely ignoring the fact that I specified jQuery and is operating as if I had run just npm install --only=prod.

Platform Info

$ npm --versions
{ adf: '1.0.0',
  npm: '6.8.0',
  ares: '1.14.0',
  cldr: '33.1',
  http_parser: '2.8.0',
  icu: '62.1',
  modules: '64',
  napi: '3',
  nghttp2: '1.34.0',
  node: '10.14.1',
  openssl: '1.1.0j',
  tz: '2018e',
  unicode: '11.0',
  uv: '1.23.2',
  v8: '6.8.275.32-node.36',
  zlib: '1.2.11' }

$ node -p process.platform
darwin

(Moved to #support. Reference: Why did you move my topic from #bugs? )

npm is working as intended, although not the way you you expected. Hopefully I can give you enough clues to have it make sense.

The devDependencies of a package you install this way are never installed (try it and see). The --only=prod is applying to which packages get installed into your node_modules from the install list, which in your case is explicitly jquery. Which you specified is not a production dependency so does not get installed!

npm is doing a thing you asked, as documented:

--save-dev : Package will appear in your devDependencies .

https://docs.npmjs.com/cli/install

Mmm, I disagree. The priority is clearly the “install” command. That is what should take precedence here. I’m very explicitly telling npm that I want to install jquery. You’re arguing that priority should be given to the —save-dev flag, but I don’t think that a flag should take priority over “install this package that I’m telling you to install”.

In short, this is bad behavior because a flag should never take precedence over an explicit command. “Install” means “come hell or high water, install this thing that I’ve told you to install.” I can work around this in my implementation, but I’m going to tell my users that npm is broken.

You’re arguing that priority should be given to the —save-dev flag

No, I’m saying that --only=prod modifies the behaviour to only install production packages. The main use case is when you don’t specify which packages, like:

npm install --only=prod

I don’t think you have to “work around” anything. To achieve what I interpret your goal to be with:

I wanted to install a package, add it to my devDependencies list, and install only the production dependencies of the package in question.

I think the command you want is:

npm install jquery --save-dev

This will install jquery, add it to the devDependencies list (if not already present), and install only the production dependencies of jquery.

Thanks; I’ll give that a shot.

I still think this behavior is incorrect because npm ends up installing nothing when -only=prod is passed. It seems to me that either:

  1. the -only=prod flag should be reserved for when npm is run without any packages explicitly listed after the install command, and should produce an error when it’s passed with an explicit list of packages to install

Or

  1. the meaning of -only=prod should change when it’s passed with an explicit list of packages after an install command. Instead of applying to the whole project, it should apply only to the packages listed after “install.”

Because, again, the current situation results in an install command that fails to install anything. That is broken.