如何覆盖嵌套的 NPM 依赖版本?
Posted
技术标签:
【中文标题】如何覆盖嵌套的 NPM 依赖版本?【英文标题】:How do I override nested NPM dependency versions? 【发布时间】:2013-03-26 05:29:43 【问题描述】:我想使用grunt-contrib-jasmine
NPM 包。它有各种依赖关系。部分依赖图如下所示:
─┬ 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
?
一些额外的上下文:
grunt-contrib-jasmine
明确需要 "~0.2.0"
的 grunt-lib-phantomjs
版本,这明确需要 phantomjs
的版本 "~1.8.1"
。
首先将phantomjs
添加到我的包的依赖项中没有效果;两个版本都已安装,grunt-contrib-jasmine
仍使用旧版本(请参阅:When installing a package with NPM, can you tell it to use a different version of one of its dependencies?)。
【问题讨论】:
只需git clone
或 fork 所需的模块。您也可以手动移除嵌套的phantomjs
。
grunt-contrib-jasmine
在 0.5.1 上,它使用 grunt-lib-phantomjs@0.3.1
,它使用 phantomjs@1.9.1-0
:)
npm 计划在未来发布overrides
overrides
现在是一个内置功能。请参阅下面的my answer。
【参考方案1】:
您可以使用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/)
【讨论】:
当我这样做时,只安装了grunt-contrib-connect
依赖项及其子项。我在 package.json 中的所有其他依赖项都没有安装。
我遇到了与@iDVB 相同的问题。我最终编辑了node_modules
目录,以便完整的shrinkwrap 依赖转储正是我想要的,而不仅仅是覆盖。但仍然是一种痛苦的解决方案。
@Domi 这个文件是通过运行 npm shrinkwrap 创建的,条目不是手动添加的
不幸的是,正如那个错误中提到的那样,对于 npm4,简约的方法不再有效。 (删除node_modules
时,使用最小收缩包装运行安装似乎使devDependencies
完好无损,尽管忽略dependencies
,但运行另一个安装会删除非显式项目,所以现在运行npm shrinkwrap
很重要获取完整文件,修改有问题的部分,然后再次运行npm install
)
npm 6.4 只会覆盖收缩包装文件并使用过时的依赖项【参考方案2】:
对于 2018 年及以后的用户,使用 npm 版本 5 或更高版本:编辑您的 package-lock.json
:从 "requires"
部分删除库并将其添加到“依赖项”下。
例如,您希望 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"
,
从"requires"
中删除"glob": "7.1.2",
,添加具有正确版本的"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 install
运行一次。在我的情况下,编辑是必要的,因为嵌套的 dep 导致失败。
这将在您运行 npm i
时被删除,而不是编辑您的 package-lock.json 并将子依赖项添加到“依赖项”,将子依赖项添加到您的 package.json “依赖项”部分
我已经创建了一个库,可以自动为您完成这些工作:github.com/rogeriochaves/npm-force-resolutions
它可以工作,但是如果我再次运行npm install
,那么对package-lock.json
的所有更改都会恢复,并且我会得到错误版本的dep。
我运行npm ci
,这不会触及package-lock.json
【参考方案3】:
对于那些使用纱线的人。
我尝试使用 npm shrinkwrap,直到我发现 yarn cli 忽略了我的 npm-shrinkwrap.json 文件。
Yarn 为此提供了https://yarnpkg.com/lang/en/docs/selective-version-resolutions/。整洁。
也请查看此答案:https://***.com/a/41082766/3051080
【讨论】:
【参考方案4】:我遇到了一个问题,其中一个嵌套依赖项存在 npm 审计漏洞,但我仍想维护父依赖项版本。 npm shrinkwrap 解决方案对我不起作用,所以我做了什么来覆盖嵌套的依赖版本:
-
删除 package-lock.json 中“requires”部分下的嵌套依赖项
在 package.json 中的 DevDependencies 下添加更新的依赖项,以便需要它的模块仍然能够访问它。
npm 我
【讨论】:
使用 npm 6 这不起作用。 npm i 覆盖对包锁定文件的任何更改【参考方案5】:对我有用的唯一解决方案(节点 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
。
【讨论】:
提示:为npm install
使用--save-dev
标志
如果只想为一个特定的第 3 方依赖项升级相应的依赖项,这将不起作用
注意:这仅在您启用 package-lock.json 时有效,某些开发人员可能由于其固有问题而没有启用。
2021 年最新版本的 NPM 中是否有任何内置解决方案?我不想依赖第三方库来处理这种事情 - 操作依赖树。
@DaniP。 npm 是穷人的 man 依赖管理器,所以我怀疑它【参考方案6】:
@user11153 的答案在本地对我有用,但是在尝试进行全新安装(又名删除 node_modules
)时,我会得到:
npm-force-resolutions: command not found
我必须将preinstall
脚本更新为:
"preinstall": "npm i npm-force-resolutions && npm-force-resolutions"
这可确保在尝试运行之前安装 npm-force-resolutions
包。
话虽如此,如果您能够改用 yarn,我会这样做,然后使用 @Gus 的答案。
【讨论】:
我使用了"preinstall": "npx force-resolutions"
,这里建议github.com/rogeriochaves/npm-force-resolutions/issues/…
还有一条更快的路线,通过bash
ery:***.com/a/68095189/132735【参考方案7】:
我正要走 npm-force-resolutions
路线,但似乎只需将依赖项包含在我自己的 package.json
中即可解决我的问题。
我相信这对我来说是可行的,因为原始依赖项允许我想要更新的相关依赖项的补丁版本。因此,通过手动包含一个较新的版本,它仍然满足原始依赖项的依赖项,并将使用我手动添加的那个。
示例
问题
我需要将 plyr
从 3.6.8
更新到版本 3.6.9
我的
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
更新我的
这会更新我的package.json
中的plyr
依赖项。
package.json
"dependencies":
"plyr": "^3.6.9",
"react-plyr": "^3.2.0"
【讨论】:
【参考方案8】:用完全不同的包进行嵌套替换
如果您只是对覆盖包的版本号感兴趣,那么此处其他答案中概述的大多数策略都可以很好地工作,但在我们的例子中,我们需要找到一种方法来覆盖嵌套的 npm 子依赖项 完全不同的包。有关您为什么要这样做的详细信息,请参阅以下问题:
How to override a nested npm sub-dependency with a different package altogether (not just different package version number)?
直接指定压缩包
要使用其他人提到的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
时正常工作,您需要在 package.json
的 scripts
部分下添加一个 preinstall
条目:
"scripts":
"preinstall": "npx npm-force-resolutions"
【讨论】:
谢谢,这真的很有用。我认为可以通过使用引用覆盖来替换包,例如"bar": "$foo"
如上一个示例 here 中所述,但我无法让它工作。但你的解决方案成功了,我会为细节加分。【参考方案9】:
截至 NPM v8.3,处理此问题的正确方法是通过 package.json
文件的 overrides
部分。
如果您需要对您的依赖项进行特定更改 依赖项,例如将依赖项的版本替换为 已知的安全问题,用 fork 替换现有依赖项,或 确保在任何地方都使用相同版本的包, 那么你可以添加一个覆盖。
覆盖提供了一种替换依赖树中的包的方法 使用另一个版本,或完全使用另一个包。这些变化可以 范围可以根据需要具体或模糊。
确保软件包 foo 始终安装为版本 1.0.0 否 不管你的依赖依赖什么版本:
"overrides": "foo": "1.0.0"
还有许多其他更细微的配置,允许您仅在某个包是特定包层次结构的依赖项时才覆盖该包。更多详情,请查看https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides
【讨论】:
@georgebrock 请考虑将此标记为正确答案 - 自从您提出问题后,生态系统发生了变化,这是 Google 的高排名结果以上是关于如何覆盖嵌套的 NPM 依赖版本?的主要内容,如果未能解决你的问题,请参考以下文章