npm 相当于 yarn 分辨率?

npm equivalent of yarn resolutions?

是否有 npm 等价于 yarn resolutions functionality? There is no mention of it in the npm package.json docs

例如,我还想在 3.3.2 上安装 lerna@3.3.2 及其依赖项之一 (@lerna/publish)。目前使用 yarn 这样做,但更愿意使用 npm 而不是手动更改 package-lock.json 或任何类似的狡猾。

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

这似乎不受 npm 本身的支持,但是这个包旨在添加这个功能:

https://github.com/rogeriochaves/npm-force-resolutions

is due to support overrides,相当于yarn的resolutions.

有关当前 RFC 状态的更多信息:

https://github.com/npm/rfcs/blob/latest/accepted/0036-overrides.md

据我所知,npm-force-resolutions 不适用于 v7. The package-lock.json format changed in v7,并且 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.json scripts 并定义 resolutions 字段,例如

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

resolutions 只是包名称的映射以及应该保留在依赖关系树中的那些包的确切版本,即上述配置将删除所有不存在的 版本5.6.0。只要你安装 webpack@5.6.0 版本作为你正在使用的项目的依赖项,这将保证所有包加载相同版本的 webpack。

Npm 相当于 yarn 分辨率被覆盖。 RFC was accepted now there's an epic to watch the progress of implementation. https://github.com/npm/statusboard/issues/343

之后

编辑:这是在 npm v8.3.0

中发布的

文档: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"
  }
}

在 package.json 中添加类似这样的内容以将任何 grapahql 包(替换为您的问题包)解析为指定版本。

  "resolutions": {
    "graphql": "^15.8.0",
    "**/graphql": "^15.8.0"
  },

您可以列出已使用 npm list <package name> 安装的软件包,以查看需要哪个软件包以及在哪里。未经测试,但认为它可以在我的机器上运行。