448

我想使用grunt-contrib-jasmineNPM 包。它有各种依赖关系。部分依赖图如下所示:

─┬ grunt-contrib-jasmine@0.4.1
 │ ├─┬ grunt-lib-phantomjs@0.2.0
 │ │ ├─┬ phantomjs@1.8.2-2

不幸的是,此版本phantomjs中存在一个错误,导致它无法在 Mac OS X 上正确安装。这已在最新版本中得到修复。

我怎样才能grunt-lib-phantomjs使用更新版本的phantomjs?

一些额外的上下文:

4

9 回答 9

282

您可以使用npm shrinkwrap功能,以覆盖任何依赖项或子依赖项。

我刚刚在grunt我们的一个项目中做到了这一点。我们需要更新版本的连接,因为2.7.3. 给我们带来了麻烦。所以我创建了一个名为npm-shrinkwrap.json

{
  "dependencies": {
    "grunt-contrib-connect": {
      "version": "0.3.0",
      "from": "grunt-contrib-connect@0.3.0",
      "dependencies": {
        "connect": {
          "version": "2.8.1",
          "from": "connect@~2.7.3"
        }
      }
    }
  }
}

npm应该在为项目安装时自动选择它。

(参见:https ://nodejs.org/en/blog/npm/managing-node-js-dependencies-with-shrinkwrap/ )

于 2013-07-02T11:05:01.800 回答
117

对于 2018 年及以后的版本,使用 npm 5 或更高版本:编辑您的package-lock.json: remove the library from "requires"section 并将其添加到“依赖项”下。

例如,您希望deglob包使用glob包版本3.2.11而不是当前版本。您打开package-lock.json并看到:

"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"
  }
},

"glob": "7.1.2",从中删除"requires",添加"dependencies"正确的版本:

"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"
    }
  }
},

现在删除您的node_modules文件夹,运行npm ci(或npm install旧版本的 node/npm),它将向该部分添加缺少的"dependencies"部分。


从 npm cli v8.3.0 (2021-12-09) 开始,这可以使用package.jsonoverrides字段来解决。StriplingWarrior 的回答中所述

于 2018-01-30T15:03:22.517 回答
84

唯一对我有用的解决方案(节点 12.x,npm 6.x)是使用由@Rogerio Chaves开发的npm-force-resolutions

首先,通过以下方式安装它:

npm install npm-force-resolutions --save-dev

--ignore-scripts如果某些损坏的传递依赖脚本阻止您安装任何东西,您可以添加。

然后package.json定义应该覆盖的依赖项(您必须设置确切的版本号):

"resolutions": {
  "your-dependency-name": "1.23.4"
}

并在"scripts"部分添加新的预安装条目:

"preinstall": "npm-force-resolutions",

现在,npm install将应用更改并强制所有依赖项your-dependency-name处于版本1.23.4

于 2020-07-17T14:27:38.560 回答
68

从 NPM v8.3开始,处理此问题的正确方法是通过文件的overrides部分package.json

如果您需要对依赖项的依赖项进行特定更改,例如用已知的安全问题替换依赖项的版本,用分叉替换现有的依赖项,或者确保在任何地方都使用相同版本的包,那么你可以添加一个覆盖。

覆盖提供了一种将依赖关系树中的包替换为另一个版本或完全替换为另一个包的方法。这些更改的范围可以根据需要具体或模糊。

为了确保软件包 foo 始终安装为 1.0.0 版本,无论您的依赖项依赖什么版本:

{
  "overrides": {
    "foo": "1.0.0"
  }
}

还有许多其他更细微的配置,允许您仅在包是特定包层次结构的依赖项时覆盖包。有关更多详细信息,请查看https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides

于 2021-12-17T16:31:04.793 回答
63

对于那些使用纱线的人。

我尝试使用 npm shrinkwrap,直到我发现 yarn cli 忽略了我的 npm-shrinkwrap.json 文件。

Yarn 对此有https://yarnpkg.com/lang/en/docs/selective-version-resolutions/。整洁的。

也看看这个答案:https ://stackoverflow.com/a/41082766/3051080

于 2019-03-19T13:10:40.163 回答
2

我遇到了一个问题,其中一个嵌套依赖项存在 npm 审计漏洞,但我仍然想维护父依赖项版本。npm shrinkwrap 解决方案对我不起作用,所以我做了什么来覆盖嵌套的依赖版本:

  1. 删除 package-lock.json 中“requires”部分下的嵌套依赖项
  2. 在 package.json 中的 DevDependencies 下添加更新的依赖项,以便需要它的模块仍然能够访问它。
  3. npm 我
于 2020-04-14T09:24:12.790 回答
2

我正要走这npm-force-resolutions条路,但似乎只需将依赖项包含在我自己的依赖项中package.json就可以解决我的问题。

我相信这对我来说是可行的,因为原始依赖项允许我想要更新的相关依赖项的补丁版本。因此,通过手动包含一个较新的版本,它仍然满足原始依赖项的依赖项,并将使用我手动添加的那个。

例子

问题

我需要更新到plyr版本3.6.93.6.8

package.json

{
  "dependencies": {
    "react-plyr": "^3.2.0"
  }
}

反应 Plyr

package.json

{
  "dependencies": {
    "plyr": "^3.6.8"
  }
}

注意plyr它以这开头的依赖^意味着它可以接受任何小补丁。您可以在此处了解更多信息:

https://docs.npmjs.com/about-semantic-versioning#using-semantic-versioning-to-specify-update-types-your-package-can-accept

更新我的

这会更新plyr我的package.json.

package.json

{
  "dependencies": {
    "plyr": "^3.6.9",
    "react-plyr": "^3.2.0"
  }
}
于 2021-10-15T20:24:33.847 回答
2

使用完全不同的包进行嵌套替换

如果您只是对覆盖包的版本号感兴趣,那么此处其他答案中概述的大多数策略都可以很好地工作,但在我们的例子中,我们需要找到一种方法来完全覆盖具有不同包的嵌套 npm 子依赖项。有关您为什么要这样做的详细信息,请参阅以下问题:

如何用不同的包完全覆盖嵌套的 npm 子依赖项(不仅仅是不同的包版本号)?

直接指定tarball

对于使用其他人提到的策略将包嵌套替换为完全不同的包npm-force-resolutions,您只需提供指向通常指定覆盖版本号的 tarball 的链接。

例如,对于用这个包ansi-html的固定分支替换易受攻击的包的情况ansi-html-community,您的解决方案部分package.json应该如下所示:

"resolutions": {
    "ansi-html": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz"
}

要找到 tarball 的链接,请使用以下命令,根据需要修改您的注册表:

npm view ansi-html-community dist.tarball --registry=https://registry.npmjs.org/

另外,请注意,要npm-force-resolutions在运行时工作npm install,您需要在以下部分preinstall下输入一个条目:scriptspackage.json

  "scripts": {
    "preinstall": "npx npm-force-resolutions"
  }
于 2021-11-30T23:11:45.997 回答
1

@user11153 的答案在本地对我有用,但是在尝试进行全新安装(又名删除node_modules)时,我会得到:

npm-force-resolutions: command not found

我必须将preinstall脚本更新为:

"preinstall": "npm i npm-force-resolutions && npm-force-resolutions"

这可确保npm-force-resolutions在尝试运行该软件包之前已安装该软件包。

话虽这么说,如果您能够改用纱线,我会这样做,然后使用@Gus 的答案。

于 2021-09-13T20:06:10.870 回答