Reputation: 30143
I would like to use the grunt-contrib-jasmine
NPM package. It has various dependencies. Part of the dependency graph looks like this:
─┬ [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
Unfortunately, there's a bug in this version phantomjs
which prevents it from installing correctly on Mac OS X. This is fixed in the latest version.
How can I get grunt-lib-phantomjs
to use a newer version of phantomjs
?
Some additional context:
grunt-contrib-jasmine
explicitly requires version "~0.2.0"
of grunt-lib-phantomjs
, which explicitly requires version "~1.8.1"
of phantomjs
.phantomjs
to my package's dependencies first has no effect; both versions are installed and grunt-contrib-jasmine
still uses the older versions (see: When installing a package with NPM, can you tell it to use a different version of one of its dependencies?).Upvotes: 725
Views: 594055
Reputation: 8916
The only solution that worked for me (node 12.x, npm 6.x) was using npm-force-resolutions developed by @Rogerio Chaves.
First, install it by:
npm install npm-force-resolutions --save-dev
You can add --ignore-scripts
if some broken transitive dependency scripts are blocking you from installing anything.
Then in package.json
define what dependency should be overridden (you must set exact version number):
"resolutions": {
"your-dependency-name": "1.23.4"
}
and in "scripts"
section add new preinstall entry:
"preinstall": "npm-force-resolutions",
Now, npm install
will apply changes and force your-dependency-name
to be at version 1.23.4
for all dependencies.
Upvotes: 105
Reputation: 3032
Based on the rest of the answers, I provide the same solution, but I display the package.json, as I struggled a little bit on where to place the override and how.
{
"name": "my-app",
"version": "snapshot",
"scripts": {
"ng": "ng",
"build-dev": "ng build --configuration development",
},
"private": true,
"dependencies": {
"@angular/animations": "~14.2.9",
"@angular/common": "~14.2.9"
...
},
"devDependencies": {
"@angular-devkit/build-angular": "^14.2.8",
....
},
"overrides": {
"loader-utils@>2.0.0 <3": "2.0.4",
"loader-utils@>3.0.0 <4": "3.2.1"
}
}
For November 2022 "loader-utils" security vulnerability, it was requested to
And to verify
Upvotes: 15
Reputation: 3363
You can use npm shrinkwrap functionality, in order to override any dependency or sub-dependency.
I've just done this in a grunt
project of ours. We needed a newer version of connect, since 2.7.3
. was causing trouble for us. So I created a file named npm-shrinkwrap.json
:
{
"dependencies": {
"grunt-contrib-connect": {
"version": "0.3.0",
"from": "[email protected]",
"dependencies": {
"connect": {
"version": "2.8.1",
"from": "connect@~2.7.3"
}
}
}
}
}
npm
should automatically pick it up while doing the install for the project.
(See: https://nodejs.org/en/blog/npm/managing-node-js-dependencies-with-shrinkwrap/)
Upvotes: 289
Reputation: 7565
As of npm cli v8.3.0 (2021-12-09) this can be solved using the overrides
field of package.json. As described in StriplingWarrior's answer
For example, the project has typescript
version 4.6.2
as direct development dependency and awesome-typescript-loader
that uses old version 2.7
of typescript
. Here is how you can tell npm
to use version 4.6.2
of typescript
for awesome-typescript-loader
:
{
"name": "myproject",
"version": "0.0.0",
"scripts": ...
"dependencies": ...
"devDependencies": {
"typescript": "~4.6.2",
"awesome-typescript-loader": "^5.2.1",
...
},
"overrides": {
"awesome-typescript-loader": {
"typescript": "$typescript"
}
}
}
If you don't use typescript
as direct development dependency, then you have to write 4.6.2
instead of $typescript
in overrides
section:
{
"name": "myproject",
"version": "0.0.0",
"scripts": ...
"dependencies": ...
"devDependencies": {
"awesome-typescript-loader": "^5.2.1",
...
},
"overrides": {
"awesome-typescript-loader": {
"typescript": "~4.6.2"
}
}
}
For using the latest version of dependency:
{
"name": "myproject",
"version": "0.0.0",
"scripts": ...
"dependencies": ...
"devDependencies": {
"awesome-typescript-loader": "^5.2.1",
...
},
"overrides": {
"awesome-typescript-loader": {
"typescript": "latest"
}
}
}
Same overrides
can be used for both dependencies
and devDependencies
.
If you're using npm version >5 but <8.3.0: edit your package-lock.json
: remove the library from "requires"
section and add it under "dependencies".
For example, you want deglob
package to use glob
package version 3.2.11
instead of its current one. You open package-lock.json
and see:
"deglob": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.0.tgz",
"integrity": "sha1-TUSr4W7zLHebSXK9FBqAMlApoUo=",
"requires": {
"find-root": "1.1.0",
"glob": "7.1.2",
"ignore": "3.3.5",
"pkg-config": "1.1.1",
"run-parallel": "1.1.6",
"uniq": "1.0.1"
}
},
Remove "glob": "7.1.2",
from "requires"
, add "dependencies"
with proper version:
"deglob": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.0.tgz",
"integrity": "sha1-TUSr4W7zLHebSXK9FBqAMlApoUo=",
"requires": {
"find-root": "1.1.0",
"ignore": "3.3.5",
"pkg-config": "1.1.1",
"run-parallel": "1.1.6",
"uniq": "1.0.1"
},
"dependencies": {
"glob": {
"version": "3.2.11"
}
}
},
Now remove your node_modules
folder, run npm ci
(or npm install
for old version of node/npm) and it will add missing parts to the "dependencies"
section.
Upvotes: 405
Reputation: 21156
I could not get the override technique to work for me, at least not to prevent the error. 1
I also couldn't use --force
or --legacy-peer-deps
as in npm install --force
. I can run npm install --force
locally but I don't know how to run that command on the server (I happen to use Google AppEngine, deployed using gcloud.cmd app deploy
)
I was able to fix my issue with two steps:
npm ci
(instead of npm install
, read about the difference here)
npm ci
will never write to package.json or any of the package-locks: installs are essentially frozen."For the record here is my entire error message, similar to the one seen here and here
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/cypress
npm ERR! dev cypress@"^9.1.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer cypress@"^4.5.0" from [email protected]
npm ERR! node_modules/cypress-plugin-snapshots
npm ERR! dev cypress-plugin-snapshots@"^1.4.4" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See C:\Users\there\AppData\Local\npm-cache\eresolve-report.txt for a full report.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\there\AppData\Local\npm-cache\_logs\2024-01-05T07_42_59_544Z-debug.log
1
Maybe my overrides
does not work because of the bug mentioned here and here. Those bugs say overrides
only work on a "fresh" install, when there is no node_modules
and no package-lock.json
. I will double-check this...
Upvotes: 0
Reputation: 156654
As of npm v8.3 (released with Node.js 16), the correct way to deal with this is via the overrides
section of your package.json
file.
If you need to make specific changes to dependencies of your dependencies, for example replacing the version of a dependency with a known security issue, replacing an existing dependency with a fork, or making sure that the same version of a package is used everywhere, then you may add an override.
Overrides provide a way to replace a package in your dependency tree with another version, or another package entirely. These changes can be scoped as specific or as vague as desired.
To make sure the package foo is always installed as version 1.0.0 no matter what version your dependencies rely on:
{ "overrides": { "foo": "1.0.0" } }
There are a variety of other, more nuanced configurations allowing you to only override a package when it's a dependency of a particular package hierarchy. For more details, check out https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides
Upvotes: 314
Reputation: 556
@user11153 's answer worked for me locally, but when trying to do a clean install (aka deleting node_modules
), I would get:
npm-force-resolutions: command not found
I had to update the preinstall
script to be:
"preinstall": "npm i npm-force-resolutions && npm-force-resolutions"
Which ensures that npm-force-resolutions
package is installed before attempting to run it.
That being said, if you're able to use yarn instead, I would do that and then use @Gus 's answer.
Upvotes: 3
Reputation: 1
Run this first
npm i -D @types/[email protected]
it will solve the issue
Upvotes: -10
Reputation: 1726
Most of the strategies outlined in the other answers here work well if you are just interested in overriding the package's version number, but in our case, we needed to find a way to override a nested npm sub-dependency with a different package altogether. For details on why you would ever want to do this, please refer to the following question:
For nested replacement of a package with an entirely different package using the npm-force-resolutions
strategy that others have mentioned, you just need to provide a link to the tarball where you would normally specify the overriding version number.
As an example, for the case of replacing the vulnerable package, ansi-html
, with the fixed fork of this package, ansi-html-community
, your resolutions section of package.json
should look like this:
"resolutions": {
"ansi-html": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz"
}
To find the link to the tarball, use the following command, modifying your registry as necessary:
npm view ansi-html-community dist.tarball --registry=https://registry.npmjs.org/
Also, note that for npm-force-resolutions
to work when you run npm install
, you will need a preinstall
entry under the scripts
section of package.json
:
"scripts": {
"preinstall": "npx npm-force-resolutions"
}
Upvotes: 13
Reputation: 14903
I was about to go down the npm-force-resolutions
route but it seems that simply including the dependency in my own package.json
fixed the problem for me.
I believe this worked in my case because the original dependency allows for patch versions of the dependency in question that I wanted to update. Thus by manually including a newer version it still fulfilled the dependency of the original dependency and will use the one I've manually added.
I need to update plyr
to version 3.6.9
from 3.6.8
package.json
{
"dependencies": {
"react-plyr": "^3.2.0"
}
}
package.json
{
"dependencies": {
"plyr": "^3.6.8"
}
}
Notice for the
plyr
dependency it starts with^
this means it can accept any minor patches. You can learn more about that here:
This updates the plyr
dependency from my package.json
.
package.json
{
"dependencies": {
"plyr": "^3.6.9",
"react-plyr": "^3.2.0"
}
}
Upvotes: 2
Reputation: 31
I had an issue where one of the nested dependency had an npm audit vulnerability, but I still wanted to maintain the parent dependency version. the npm shrinkwrap solution didn't work for me, so what I did to override the nested dependency version:
Upvotes: 2
Reputation: 7555
For those using yarn.
I tried using npm shrinkwrap until I discovered the yarn cli ignored my npm-shrinkwrap.json file.
Yarn has https://yarnpkg.com/lang/en/docs/selective-version-resolutions/ for this. Neat.
Check out this answer too: https://stackoverflow.com/a/41082766/3051080
Upvotes: 68