我想使用 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 明确需要 grunt-lib-phantomjs 的“~0.2.0”版本,它明确需要 phantomjs 的“~1.8.1”版本。
首先将 phantomjs 添加到我的包的依赖项中没有效果;两个版本都已安装,并且 grunt-contrib-jasmine 仍然使用旧版本(请参阅:使用 NPM 安装包时,你能告诉它使用其依赖项之一的不同版本吗?)。
您可以使用 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/)
从 npm cli v8.3.0 (2021-12-09) 开始,可以使用 package.json 的 overrides
field 解决此问题。 如 StriplingWarrior's answer 中所述
例如,该项目具有 typescript
版本 4.6.2
作为 direct 开发依赖项,而 awesome-typescript-loader
使用旧版本 2.7
的 typescript
。以下是告诉 npm
将 typescript
的 4.6.2
版本用于 awesome-typescript-loader
的方法:
{
"name": "myproject",
"version": "0.0.0",
"scripts": ...
"dependencies": ...
"devDependencies": {
"typescript": "~4.6.2",
"awesome-typescript-loader": "^5.2.1",
...
},
"overrides": {
"awesome-typescript-loader": {
"typescript": "$typescript"
}
}
}
如果您不使用 typescript
作为 direct 开发依赖项,那么您必须在 overrides
部分编写 4.6.2
而不是 $typescript
:
{
"name": "myproject",
"version": "0.0.0",
"scripts": ...
"dependencies": ...
"devDependencies": {
"awesome-typescript-loader": "^5.2.1",
...
},
"overrides": {
"awesome-typescript-loader": {
"typescript": "~4.6.2"
}
}
}
dependencies
和 devDependencies
可以使用相同的 overrides
。
如果您使用的是 npm 版本 >5 但 <8.3.0:编辑您的 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 “依赖项”部分
npm install
,那么对 package-lock.json
的所有更改都会恢复,并且我会恢复错误版本的 dep。
npm ci
,但它没有触及 package-lock.json
从 NPM v8.3 开始,处理此问题的正确方法是通过 package.json
文件的 overrides
部分。
如果您需要对依赖项的依赖项进行特定更改,例如用已知的安全问题替换依赖项的版本,用分叉替换现有的依赖项,或者确保在任何地方都使用相同版本的包,那么你可以添加一个覆盖。覆盖提供了一种将依赖关系树中的包替换为另一个版本或完全替换为另一个包的方法。这些更改的范围可以根据需要具体或模糊。确保软件包 foo 始终安装为版本 1.0.0,无论您的依赖项依赖什么版本:{“overrides”:{“foo”:“1.0.0”}}
还有许多其他更细微的配置,允许您仅在包是特定包层次结构的依赖项时覆盖包。有关详细信息,请查看 https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides
"engines": { "npm": ">=8.3.0" }
添加到您的 package.json 以指示需要新的 npm 版本
.npmrc
中使用 engine-strict=true
对其进行了扩展,不仅会收到警告,因为需要覆盖的依赖项对我们来说有很大的破坏性。
唯一对我有用的解决方案(节点 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
标志
"preinstall": "npm install --package-lock-only --ignore-scripts && npx npm-force-resolutions"
请参阅 stackoverflow.com/a/67446313/6627882
对于那些使用纱线的人。
我尝试使用 npm shrinkwrap,直到我发现 yarn cli 忽略了我的 npm-shrinkwrap.json 文件。
为此,Yarn 有 https://yarnpkg.com/lang/en/docs/selective-version-resolutions/。整洁的。
也请查看此答案:https://stackoverflow.com/a/41082766/3051080
使用完全不同的包进行嵌套替换
如果您只是对覆盖包的版本号感兴趣,那么此处其他答案中概述的大多数策略都可以很好地工作,但是在我们的例子中,我们需要找到一种方法来完全覆盖具有不同包的嵌套 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 install
时使 npm-force-resolutions
工作,您需要在 package.json
的 scripts
部分下有一个 preinstall
条目:
"scripts": {
"preinstall": "npx npm-force-resolutions"
}
"bar": "$foo"
)覆盖来替换包,但我无法让它工作。但是你的解决方案成功了,我会为细节多加一点。
我遇到了一个问题,其中一个嵌套依赖项存在 npm 审计漏洞,但我仍然想维护父依赖项版本。 npm shrinkwrap 解决方案对我不起作用,所以我做了什么来覆盖嵌套的依赖版本:
删除 package-lock.json 中 'requires' 部分下的嵌套依赖项 在 package.json 中的 DevDependencies 下添加更新的依赖项,以便需要它的模块仍然能够访问它。 npm 我
@user11153 的答案在本地对我有用,但是在尝试进行全新安装(又名删除 node_modules
)时,我会得到:
npm-force-resolutions: command not found
我必须将 preinstall
脚本更新为:
"preinstall": "npm i npm-force-resolutions && npm-force-resolutions"
这可确保在尝试运行之前安装 npm-force-resolutions
包。
话虽这么说,如果您能够改用纱线,我会这样做,然后使用@Gus 的答案。
"preinstall": "npx force-resolutions"
github.com/rogeriochaves/npm-force-resolutions/issues/…
bash
ery: stackoverflow.com/a/68095189/132735
我正要走 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"
}
}
先运行这个
npm i -D @types/eslint@8.4.3
它将解决问题
不定期副业成功案例分享
grunt-contrib-connect
依赖项及其子项。我在 package.json 中的所有其他依赖项都没有安装。node_modules
目录,以便完整的收缩包装依赖转储正是我想要的,而不仅仅是覆盖。但仍然是一种痛苦的解决方案。node_modules
时,尽管忽略dependencies
,但使用最小的收缩包装运行安装似乎会使devDependencies
完好无损,但运行另一个安装会删除非显式项,因此现在运行npm shrinkwrap
以获取完整文件,修改相关部分,然后再次运行npm install
)