[BUG] npm prefers `devDependencies` to `dependencies`
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 10.1k
- Forks
- 4.7k
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 19
Description
Is there an existing issue for this?
- I have searched the existing issues
This issue exists in the latest npm version
- I am using the latest npm
Current Behavior
When a package is included in both dependencies and devDependencies npm install will install the devDependencies
- npm will mark the package 'dev', commands like
--omit devwill not install the package - npm will satisfy the edge defined by the devDependencies, not dependencies
- this happens whether the spec's overlap or not
Expected Behavior
I expect npm to either error, or prefer the dependencies. Preferring devDependencies leads to a number of confusing behaviors
- Creating a production bundle with
npm install --omit devdoes not include one of the prod dependencies - Installing the package as a dependency will install the prod dependency, which may not be the same spec the package was tested or built with
Steps To Reproduce
Create an example package in test. Add a package to dev and normal dependencies. I chose typescript arbitrarily. You can use the same spec or a different spec. The order of dependencies and devDependencies does not matter, npm always prefers devDependencies.
{
"name": "test",
"version": "0.0.1",
"dependencies":{"typescript":"^5"},
"devDependencies":{"typescript":"^4"}
}
Install dependencies and explain typescript. You should see that it installed typescript ^4 and it's a dev dependency.
$ npm install
$ npm explain typescript
typescript@4.9.5 dev
node_modules/typescript
dev typescript@"^4" from the root project
Now let's omit dev dependencies. You should see that node_modules doesn't include any typescript.
$ npm install --omit dev
$ npm explain typescript
npm ERR! No dependencies found matching typescript
This is also a change from npm 6, where prod dependencies are preferred
$ npx -- npm@6 install
$ jq .version node_modules/typescript/package.json
"5.0.4"
$ npx -- npm@6 install --production
$ jq .version node_modules/typescript/package.json
"5.0.4"
Now lets's complete the example by demoing that npm will use the transitive prod dependency. Make a new package test2
{
"dependencies": {
"test": "file:../test"
}
}
Now when we install, using install-links true to install it as a regular dependency instead of a symlink, npm uses the dependencies. Consumers thru npm will use a completely different version that doesn't satisfy the version the package was tested with.
$ npm install --install-links=true
$ npm explain typescript
typescript@5.0.4
node_modules/typescript
typescript@"^5" from test@0.0.1
node_modules/test
test@"file:../test" from the root project
Environment
- npm: 9.6.6
- Node.js: N/A
- OS Name: N/A
- System Model Name: N/A
- npm config:
; N/A
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the behavior with the test and test2 example packages using npm install, npm explain, and --omit dev; compare it with npm 6. The issue is done when overlapping dependencies either produce an error or consistently prefer the production dependency, including when the package is installed transitively.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100