npm的等效项是什么,与yarn的resolutions相对应?

166

是否有npm的等效功能,可以像yarn resolutions那样使用?在npm package.json文档中没有提到它。

例如,我想安装lerna@3.3.2及其依赖项之一(@lerna/publish)也以3.3.2的版本进行安装。目前可以使用yarn来完成这个操作,但我更喜欢使用npm而不是手动更改package-lock.json或其他类似的操作。

"devDependencies": {
  "lerna": "3.3.2",
},
"resolutions": {
  "@lerna/publish": "3.3.2"
}

你知道 npm shrinkwrap 吗?这可能适合你。 参见:https://docs.npmjs.com/cli/shrinkwrap - Consta Gorgan
这个回答解决了你的问题吗?如何覆盖嵌套的NPM依赖版本? - Henke
5个回答

128
自从 NPM 8.3,相当于 yarn resolutions 的是 overrides
为了确保包 foo 始终安装为版本 1.0.0,无论你的依赖关系依赖于什么版本:
{
   "overrides": {
     "foo": "1.0.0"
   }
 }

文档:https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides

为什么以及如何添加这个功能在RFC中讨论,有关该主题的讨论已被编入此github issue


1
这个答案帮助我解决了问题。https://github.com/andrewrk/node-s3-client/issues/228一个npm包的github仓库被归档,引用了一个旧的npm包,在升级到新版本的NodeJS时会导致错误。https://github.com/andrewrk/node-s3-client/commit/9a1b386020049ecf5d5c8ec70817afd7b6241fed https://github.com/andrewrk/node-s3-client/blame/master/package.json#L40有问题的包已经在仓库中更新了,但是新版本没有推送到npm,因此npm包基本上永远无法使用。 - Steven

65

6
这个提交信息表明 npm-force-resolutions 的相应版本为 0.0.10,可以在 npm 7 上使用。请参考此链接 - zb226
2
2022年,它是被支持的:https://dev59.com/wFQK5IYBdhLWcg3wHsZJ#67397982 - maxkoryukov

60

1
这似乎在NPM 8.3上运行。 - ahmed
2022年,它已经默认支持:https://dev59.com/wFQK5IYBdhLWcg3wHsZJ#67397982 - maxkoryukov

20
据我所知,npm-force-resolutions 无法与 v7 兼容。在 v7 中,package-lock.json 的格式已经改变,而 npm-force-resolutions 不再更新相关字段。

不过,编写一个脚本仅限制您的依赖关系树仅使用某个包的单一版本是比较容易的,例如:

#!/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);

该脚本简单地删除所有与package.json中定义的resolutions不符合的依赖关系链接。

要执行该脚本,只需将其添加到package.jsonscripts中,并定义resolutions字段,例如:

{
  "scripts": {
    "postinstall": "node bin/fix-package-lock.js"
  },
  "resolutions": {
    "webpack": "5.6.0"
  }
}

resolutions 是一个简单的映射,它将包名和这些包的确切版本保留在依赖树中,即上面的配置将删除所有版本不是5.6.0。只要您将webpack@5.6.0版本安装为正在使用的项目的依赖项,这将保证所有包加载相同版本的webpack。


7

针对任何阅读此内容的人,自npm版本8.3.0起,覆盖已成为npm支持的功能::party:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接