Is there an existing issue for this?
This issue exists in the latest npm version
Current Behavior
When running npm dedupe on a package tree containing several instances of a package dependency at the same semver range, the package is not lifted to the root level of the package tree, and multiple versions of the package are installed.
I believe this is a result of npm installing an older version of the package at the root-level, preventing the newer shared version from being lifted to the root level. This hypothesis is supported by the fact that removing the package that relies on the older version of the dependency results in npm dedupe working correctly.
In the linked repo, @hashicorp/react-combobox depends on @reach/combobox, which depends on @reach/auto-id@0.16.0. Since this package was the first installed, npm stored @reach/auto-id@0.16.0 at node_modules/@reach/auto-id, and persisted this to package-lock.json. When @hashicorp/react-text-input and @hashicorp/react-textarea-input were installed, npm was unable to dedupe @reach/auto-id@0.17.0 because the only available storage location was already taken by @reach/auto-id@0.16.0.
npm-dedupe-issue@0.0.1 C:\Users\DylanStaley\Desktop\auto-id
├─┬ @hashicorp/react-combobox@1.1.0
│ └─┬ @reach/combobox@0.16.5
│ └── @reach/auto-id@0.16.0
├─┬ @hashicorp/react-text-input@5.0.2
│ └── @reach/auto-id@0.17.0
└─┬ @hashicorp/react-textarea-input@1.1.0
└── @reach/auto-id@0.17.0
I'm fairly sure this is a result of npm using layout data from package-lock.json since installing without a lockfile results in correct deduplication. This leads me to believe that modern versions of npm have a dedupe algorithm that can solve for this specific case, but it instead relies on the layout information from package-lock.json, resulting in a package tree that's different from what you'd receive if you had run npm install without a lockfile.
Expected Behavior
Packages that depend on the same semver range of a specific package have their dependencies deduped even if the package-lock.json lockfile has a different version of the package at the root level.
In the provided repro, after npm dedupe I'd expect @reach/auto-id@0.16.0 to be moved into node_modules/@reach/combobox/node_modules/@reach/auto-id, and @reach/auto-id@0.17.0 to be moved from node_modules/@hashicorp/react-text-input/node_modules/@reach/auto-id to node_modules/@reach/auto-id.
Steps To Reproduce
- Clone this repo.
- Run
npm install followed by npm dedupe.
- Confirm package
@reach/auto-id at v0.17.0 is not deduped by running npm ls @reach/auto-id.
Environment
- npm: 8.17.0
- Node.js: v16.14.0
- OS Name: Windows
- System Model Name: Dell XPS 15
- npm config:
; "user" config from C:\Users\DylanStaley\.npmrc
//registry.npmjs.org/:_authToken = (protected)
; node bin location = C:\Users\DylanStaley\AppData\Local\Volta\tools\image\node\16.14.0\node.exe
; cwd = C:\Users\DylanStaley\Desktop\auto-id
; HOME = C:\Users\DylanStaley
; Run `npm config ls -l` to show all defaults.
Is there an existing issue for this?
This issue exists in the latest npm version
Current Behavior
When running
npm dedupeon a package tree containing several instances of a package dependency at the same semver range, the package is not lifted to the root level of the package tree, and multiple versions of the package are installed.I believe this is a result of npm installing an older version of the package at the root-level, preventing the newer shared version from being lifted to the root level. This hypothesis is supported by the fact that removing the package that relies on the older version of the dependency results in
npm dedupeworking correctly.In the linked repo,
@hashicorp/react-comboboxdepends on@reach/combobox, which depends on@reach/auto-id@0.16.0. Since this package was the first installed, npm stored@reach/auto-id@0.16.0atnode_modules/@reach/auto-id, and persisted this topackage-lock.json. When@hashicorp/react-text-inputand@hashicorp/react-textarea-inputwere installed, npm was unable to dedupe@reach/auto-id@0.17.0because the only available storage location was already taken by@reach/auto-id@0.16.0.I'm fairly sure this is a result of npm using layout data from
package-lock.jsonsince installing without a lockfile results in correct deduplication. This leads me to believe that modern versions of npm have a dedupe algorithm that can solve for this specific case, but it instead relies on the layout information frompackage-lock.json, resulting in a package tree that's different from what you'd receive if you had runnpm installwithout a lockfile.Expected Behavior
Packages that depend on the same semver range of a specific package have their dependencies deduped even if the
package-lock.jsonlockfile has a different version of the package at the root level.In the provided repro, after
npm dedupeI'd expect@reach/auto-id@0.16.0to be moved intonode_modules/@reach/combobox/node_modules/@reach/auto-id, and@reach/auto-id@0.17.0to be moved fromnode_modules/@hashicorp/react-text-input/node_modules/@reach/auto-idtonode_modules/@reach/auto-id.Steps To Reproduce
npm installfollowed bynpm dedupe.@reach/auto-idatv0.17.0is not deduped by runningnpm ls @reach/auto-id.Environment