Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] install --only=development doesn't install needed dependencies if listed in production dependencies #1669

Closed
msbit opened this issue Aug 13, 2020 · 10 comments
Assignees
Labels
Bug thing that needs fixing Release 7.x work is associated with a specific npm 7 release

Comments

@msbit
Copy link

msbit commented Aug 13, 2020

Current Behavior:

If I have a list of dependencies and devDependencies such that devDependencies[x] depends on dependencies[y] and I run npm install --only=development, only devDependencies[x] is installed.

In a related twist, swapping the direction of dependencies (such that dependencies[x] depends on devDependencies[y]) and running npm install --only=development results in no packages being installed at all.

Expected Behavior:

When running npm install --only=development I would expect all required direct devDependencies and any transitive dependencies of any stripe (dependencies, devDependencies or unlisted) to be installed.

Steps To Reproduce:

A concrete example involves lodash and json-replace (the former with no dependencies, and the latter with only one dependency, on lodash):

$ cat package.json
{
  "name": "npm-dev-only",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "lodash": "*"
  },
  "devDependencies": {
    "json-replace": "*"
  }
}

$ rm -rf node_modules

$ npm install --only=development
npm WARN npm-dev-only@1.0.0 No description
npm WARN npm-dev-only@1.0.0 No repository field.

added 1 package from 1 contributor and audited 2 packages in 1.195s
found 8 vulnerabilities (4 low, 4 high)
  run `npm audit fix` to fix them, or `npm audit` for details

$ find node_modules -name package.json -type f
node_modules/json-replace/package.json

Swapping it around:

$ cat package.json 
{
  "name": "npm-dev-only",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "json-replace": "*"
  },
  "devDependencies": {
    "lodash": "*"
  }
}

$ rm -rf node_modules

$ npm install --only=development
npm WARN npm-dev-only@1.0.0 No description
npm WARN npm-dev-only@1.0.0 No repository field.

audited 3 packages in 0.464s
found 8 vulnerabilities (4 low, 4 high)
  run `npm audit fix` to fix them, or `npm audit` for details

$ find node_modules -name package.json -type f
find: node_modules: No such file or directory

Environment:

  • OS: macOS 10.13.6
  • Node: v14.5.0
  • NPM: 6.14.7
@msbit
Copy link
Author

msbit commented Aug 13, 2020

A bit of a script to reproduce:

mkdir npm-dev-only
pushd npm-dev-only
npm init -y
npm install --save-prod --save-exact lodash@1.3.1
npm install --save-dev --save-exact json-replace@0.0.1
rm -rf node_modules
npm install --only=development

This results in a package-lock.json as follows:

{
  "name": "npm-dev-only",
  "version": "1.0.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "json-replace": {
      "version": "0.0.1",
      "resolved": "https://registry.npmjs.org/json-replace/-/json-replace-0.0.1.tgz",
      "integrity": "sha1-mVKEpTnu1EjHgJhMf5S96HxuDpU=",
      "dev": true,
      "requires": {
        "lodash": "1.3.1"
      }
    },
    "lodash": {
      "version": "1.3.1",
      "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.3.1.tgz",
      "integrity": "sha1-pGY7U2hriV/wdOK6UE37dqjit3A="
    }
  }
}

If you don't specify a version with the npm install --save-* commands, you get the following package-lock.json:

{
  "name": "npm-dev-only",
  "version": "1.0.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "json-replace": {
      "version": "0.0.1",
      "resolved": "https://registry.npmjs.org/json-replace/-/json-replace-0.0.1.tgz",
      "integrity": "sha1-mVKEpTnu1EjHgJhMf5S96HxuDpU=",
      "dev": true,
      "requires": {
        "lodash": "1.3.1"
      },
      "dependencies": {
        "lodash": {
          "version": "1.3.1",
          "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.3.1.tgz",
          "integrity": "sha1-pGY7U2hriV/wdOK6UE37dqjit3A=",
          "dev": true
        }
      }
    },
    "lodash": {
      "version": "4.17.19",
      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
      "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
    }
  }
}

and the behaviour isn't exhibited.

@darcyclarke darcyclarke added Bug thing that needs fixing Needs Triage needs review for next steps Release 6.x work is associated with a specific npm 6 release labels Aug 14, 2020
@tyler-laberge
Copy link

We are seeing this issue too but in our case it involves transitive dependencies not being installed.

In our case we have https://www.npmjs.com/package/serverless-plugin-typescript declared in our dev dependencies, and https://www.npmjs.com/package/log4js declared in our regular dependencies. Each of these has a transitive dependency (regular not dev dependency) on the package https://www.npmjs.com/package/universalify.

package.json

{
  "name": "reproduce-npm-bug",
  "version": "1.0.0",
  "devDependencies": {
    "serverless-plugin-typescript": "^1.1.9",
    "typescript": "^3.9.7"
  },
  "dependencies": {
    "log4js": "^6.3.0"
  }
}

Regular install

npm install
npm ls universalify

reproduce-npm-bug@1.0.0 /example/reproduce-npm-bug 
├─┬ log4js@6.3.0
│ └─┬ streamroller@2.2.4
│   └─┬ fs-extra@8.1.0
│     └── universalify@0.1.2  deduped
└─┬ serverless-plugin-typescript@1.1.9
  └─┬ fs-extra@7.0.1
    └── universalify@0.1.2

Dev only install

rm -rf node_modules
npm install --only=dev
npm ls universalify

reproduce-npm-bug@1.0.0 /example/reproduce-npm-bug                                                                                                                                                       ├─┬ UNMET DEPENDENCY log4js@6.3.0
│ └─┬ UNMET DEPENDENCY streamroller@2.2.4
│   └─┬ UNMET DEPENDENCY fs-extra@8.1.0
│     └── UNMET DEPENDENCY universalify@0.1.2
└─┬ serverless-plugin-typescript@1.1.9
  └─┬ fs-extra@7.0.1
    └── UNMET DEPENDENCY universalify@0.1.2

npm ERR! missing: log4js@6.3.0, required by reproduce-npm-bug@1.0.0
npm ERR! missing: streamroller@2.2.4, required by log4js@6.3.0
npm ERR! missing: fs-extra@8.1.0, required by streamroller@2.2.4
npm ERR! missing: universalify@0.1.2, required by fs-extra@8.1.0
npm ERR! missing: universalify@0.1.2, required by fs-extra@7.0.1

I would expect that the universalify transitive dependency of serverless-plugin-typescript to be installed but it is not.

@msbit
Copy link
Author

msbit commented Aug 15, 2020

Thanks @tyler-laberge for the additional reproduction!

It does look like the same issue; if you're comfortable with it, could you try the patch from #1676 and see if that fixes it?

@ruyadorno
Copy link
Contributor

Thanks to you all for the great work documenting all this here ❤️

Unfortunately as mentioned in the linked PR these changes might be too risky for v6 at this point in time.

@isaacs I'll keep this issue around in order to serve as a placeholder to remember to add these test cases to arborist/v7 - feel free to close it after that 😊

@ruyadorno ruyadorno added beta-bug Release 7.x work is associated with a specific npm 7 release and removed Needs Triage needs review for next steps Release 6.x work is associated with a specific npm 6 release labels Aug 17, 2020
@tyler-laberge
Copy link

@msbit FWIW I just tried the patch and that does seem to fix the issue

@msbit
Copy link
Author

msbit commented Aug 19, 2020

Thanks @ruyadorno, getting this sorted out for v7 is still a good win.

@ruyadorno
Copy link
Contributor

thanks @tyler-laberge for the handy reproduction case. I tested it with the latest beta version v7.0.0-beta.12 and validate it's working as expected there 😊

Thanks @msbit for bringing this one up to our attention!

@sandstrom
Copy link

sandstrom commented Feb 9, 2022

@ruyadorno How about making a change like this?

// package.json
{
  …
  "dependencies": {
    "development": {
      "swipejs": "~2.2.14",
      "ua-parser-js": "~0.7"
    },
    "production": {
      "swipejs": "~2.2.14",
    },
    "linting": {
      "eslint": "~1.0.0"
    },
  },
  …
}

and in package-lock.json you'd have "groups" : ["development", "production", "linting"] instead of the current "dev": true flag.

That way, one could have arbitrary groups of dependencies, and you could easily resolve which ones to install during a given run, via e.g. npm install only=production,linting or npm install only=development.

A good use-case for this is to have a linting group that's only installed during certain CI-runs. But would also be backwards-compatible (functionality-wise, that is) with dev-dependencies.

@ljharb
Copy link
Contributor

ljharb commented Feb 9, 2022

Using a "dependencies" name would utterly break every npm ecosystem tool that expects it to be a deps object.

@sandstrom
Copy link

@ljharb Yes, good point! This was mostly intended as a rough draft to illustrate the idea.

I agree with you that you wouldn't want to make this breaking.

What e.g. Ruby's Bundler did when they introduced dependency groups, was that the non-specified dependencies always belong to default, and you can then add additional groups on top of that.

A similar strategy could be used here, e.g. the devDependencies and dependencies groups could certainly remain.

Just from the top of my head, you could have a syntax where prefixDependencies would be the syntax to use for other groups.

  • dependencies -> production group [old]
  • devDependencies -> dev group [old]
  • lintingDependencies -> linting group [example]
  • `{prefix}Dependencies -> {prefix} group [syntax]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug thing that needs fixing Release 7.x work is associated with a specific npm 7 release
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants