npm equivalent of yarn resolutions?
This does not seem to be supported by npm natively, however this package aims to add this functionality:
https://github.com/rogeriochaves/npm-force-resolutions
npm is due to support overrides
, which is equivalent to yarn's resolutions
.
For more information about the current RFC status:
https://github.com/npm/rfcs/blob/latest/accepted/0036-overrides.md
Npm equivalent to yarn resolutions is overrides. After the RFC was accepted now there's an epic to watch the progress of implementation. https://github.com/npm/statusboard/issues/343
Edit: This was released in npm v8.3.0
Documentation: https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides
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" } }
As far as I can tell, npm-force-resolutions
does not work with npm v7. The package-lock.json
format changed in v7 and npm-force-resolutions
no longer updates the relevant fields.
However, it is relatively easy to write a script to restrict your dependency tree to only 1 version of a package, e.g.
#!/usr/bin/env node
/* eslint-disable unicorn/prevent-abbreviations */
/* eslint-disable import/unambiguous */
/* eslint-disable import/no-commonjs */
/* eslint-disable node/shebang */
const fs = require('fs').promises;
const path = require('path');
const main = async (resolutions) => {
const packageLockFilePath = path.resolve(__dirname, '../package-lock.json');
for (const [name, version] of Object.entries(resolutions)) {
const packageLock = JSON.parse(await fs.readFile(packageLockFilePath));
const packagePaths = Object.keys(packageLock.packages);
const deletePaths = [];
for (const packagePath of packagePaths) {
if (packagePath.endsWith('/' + name)) {
if (packageLock.packages[packagePath].version !== version) {
deletePaths.push(packagePath);
}
}
}
for (const packagePath of deletePaths) {
for (const deletePath of deletePaths) {
if (packagePath === deletePath || packagePath.startsWith(deletePath + '/')) {
// eslint-disable-next-line fp/no-delete
delete packageLock.packages[packagePath];
}
}
}
await fs.writeFile(
packageLockFilePath,
JSON.stringify(packageLock, null, ' '),
);
}
};
main(require('../package.json').resolutions);
This script simply removes all links to dependencies that do not satisfy resolutions
defined in package.json
.
To execute the script, just add it to package.json
scripts
and define resolutions
field, e.g.
{
"scripts": {
"postinstall": "node bin/fix-package-lock.js"
},
"resolutions": {
"webpack": "5.6.0"
}
}
resolutions
is simply a map of package names and the exact versions of those packages that should be kept in the dependency tree, i.e. the above configuration will remove all versions of webpack that are not 5.6.0
. As long you install [email protected]
version as a dependency of the project you are working with, this will guarantee that all packages load the same version of webpack.