npm / cli

the package manager for JavaScript
https://docs.npmjs.com/cli/
Other
8.39k stars 3.12k forks source link

[BUG] `npm install --production` runs scripts #4027

Open mxschmitt opened 2 years ago

mxschmitt commented 2 years ago

Is there an existing issue for this?

This issue exists in the latest npm version

Current Behavior

When using npm install --production it executes the prepare scripts in version 7+. In version 6 it didn't execute them.

Workaround: npm install --production --ignore-scripts

(Didn't see that the behaviour has changed in the changelog or in the docs, thats why I'm filing it. The workaround is working for us)

Expected Behavior

The prepare script does not get executed.

Steps To Reproduce

  1. Create this package.json
{
  "name": "npm-install-production-prepare",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "prepare": "echo \"PREPARE GETS EXECUTED\""
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
  1. npm install --production
  2. Observe that the prepare script gets executed

Environment

mbtts commented 2 years ago

I think it might also be running build (or trying to) as well (see https://github.com/npm/cli/issues/4003).

The behaviour is certainly different to version 6 and (as far as I can see) not clearly documented.

lucaswerkmeister commented 2 years ago

I agree that this behavior doesn’t match what the documentation says:

prepare (since npm@4.0.0)

  • Runs on local npm install without any arguments
  • As of npm@7 these scripts run in the background. To see the output, run with: --foreground-scripts.

It’s also unfortunate, because under the previous behavior, it made sense to use the prepare script for steps that only make sense in a plain npm install, and put its dependencies in devDependencies; now that npm runs it on npm install --production too, it’ll crash because those dependencies can’t be found.

damianprzygodzki commented 2 years ago

Agree. After update to npm 8 (from 6) we've observed unexpected run of prepare lifeCycle script before npm install --production. It can even brake building an image with app. Documentation doesn't mention that fact.

jeongmincha commented 2 years ago

Is there any progress on this issue?

pmoleri commented 2 years ago

Given that the documentation states:

NOTE: If a package being installed through git contains a prepare script, its dependencies and devDependencies will be installed, and the prepare script will be run, before the package is packaged and installed.

Looks like npm acknowledges that prepare requires the devDependencies. I think when running --production and there's a prepare script, it should:

pkellz commented 1 year ago

Any update on this issue?

timakhalaya commented 1 year ago

any update?

as a workaround set prepare script to "" in RUN stage of Docker ???

jorenbroekema commented 8 months ago

For what it's worth, I've just started using postinstall/prepare with a NodeJS script that checks process.env.NODE_ENV before running dev-only postinstall scripts:

// only run these scripts if we install dev deps & npm install was ran inside style-dictionary package itself
// since our consumers don't ever need to run these themselves.
if (process.env.NODE_ENV !== 'production' && process.env.PWD === process.env.INIT_CWD) {
  const husky = require('husky');
  husky.install();
  // we're only patching dev deps
  require('patch-package');
}

I didn't confirm this but it seems the 2nd check in the if condition may be redundant if you use prepare over postinstall, although prepare seems to run in different lifecycle hooks as well so for me this wasn't really the right hook to use.

Note: On Windows, NODE_ENV and PWD are both undefined...... :(

robross0606 commented 4 months ago

Why are we now on npm 10 and this bug still exists?

tannerstern commented 1 month ago

I lost a few hours on this issue several weeks ago. I can't speak to what the behavior should be (at the moment I'm using a tiny shell script that checks for NODE_ENV and runs accordingly). I do agree that the documentation is misleading: I took it on face value from the v10 scripts documentation that

  • Runs on local npm install without any arguments

meant that including the --production flag would not trigger my prepare script.

In my use case, npm install --production is being called from within a Google Cloud Functions deployment, ~over which I have no control or ability to add --ignore-scripts~.

Maybe that line ought simply to be removed from the docs. I don't think I would have spent so much time scratching my head without its apparent contradiction of what I was seeing.

ljharb commented 1 month ago

@tannerstern you can add ignore-scripts: true to .npmrc, or you can set the NPM_CONFIG_IGNORE_SCRIPTS env var.

MohammedSiddiqui commented 3 weeks ago

For cases where dev dependencies don't exist when running npm install on your CI, this little snippet did the trick for me:

"prepare": "husky || true",

However, this would only work for Unix-based systems where we are ignoring any errors from the first command.