如何覆盖嵌套的NPM依赖项版本?

geo*_*ock 257 node.js npm

我想使用grunt-contrib-jasmineNPM包.它有各种依赖.依赖图的一部分如下所示:

?? grunt-contrib-jasmine@0.4.1
 ? ??? grunt-lib-phantomjs@0.2.0
 ? ? ??? phantomjs@1.8.2-2
Run Code Online (Sandbox Code Playgroud)

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

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

一些额外的背景:

Str*_*ior 283

从 npm v8.3(随Node.js 16发布)开始,处理此问题的正确方法是通过文件overrides的 部分package.json

如果您需要对依赖项的依赖项进行特定更改,例如用已知的安全问题替换依赖项的版本,用分支替换现有依赖项,或者确保到处使用相同版本的包,那么您可以添加覆盖。

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

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

{
  "overrides": {
    "foo": "1.0.0"
  }
}
Run Code Online (Sandbox Code Playgroud)

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

  • @georgebrock 请考虑将此标记为正确答案 - 自从您提出问题以来,生态系统已经发生了变化,这是一个排名很高的 Google 结果 (22认同)
  • 考虑将 `"engines": { "npm": ">=8.3.0" }` 添加到 package.json 以指示需要新的 npm 版本 (15认同)
  • 这让我很困惑:如果您将 monorepo 与工作区一起使用,则需要在根包中定义覆盖,而不是在具有实际依赖项的嵌套项目中定义覆盖。 (4认同)
  • 请注意, overrides 属性的实现存在问题,据报道它仅适用于第一个“npm install”命令:https://github.com/npm/cli/issues/5443 (3认同)
  • 来自@leumasme 的好建议!我们在“.npmrc”中使用“engine-strict=true”对其进行了扩展,不仅会收到警告,因为需要重写的依赖关系对我们来说会破坏很多。 (2认同)

tux*_*per 224

您可能已经找到了解决方法.

无论如何,您可以使用npm shrinkwrap功能,以覆盖任何依赖项或子依赖项.

我刚刚在我们的一个咕噜咕噜的项目中做到了这一点.从2.7.3开始,我们需要更新版本的connect.给我们带来了麻烦.所以我创建了一个名为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"
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

npm应该在为项目安装时自动拾取它.

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

  • 不幸的是,正如那个bug中提到的那样,使用npm4,简约方法不再有效.(当删除`node_modules`时,运行带有最小shrinkwrap的安装似乎保留`devDependencies`虽然忽略了`dependencies`,但是运行另一个安装会删除非显式项,所以现在运行`npm shrinkwrap`很重要获取完整文件,修改有问题的部分,然后再次运行`npm install`) (13认同)
  • 当我这样做时,只安装了`grunt-contrib-connect`依赖项及其子代.我没有安装package.json中的所有其他依赖项. (7认同)
  • 我和@ iDVB有同样的问题.我最终编辑了`node_modules`目录,以便完全收缩包依赖转储正是我想要的,而不仅仅是覆盖.但仍然是一种痛苦的解决方案. (5认同)
  • 虽然似乎不适用于peerDependencies? (2认同)
  • @Domi这个文件是通过运行npm shrinkwrap创建的,条目不是手工添加的 (2认同)
  • npm 6.4只会覆盖shrinkwrap文件并使用过时的依赖项 (2认同)

izo*_*fif 69

对于那些来自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"
  }
},
Run Code Online (Sandbox Code Playgroud)

删除"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"
    }
  }
},
Run Code Online (Sandbox Code Playgroud)

现在删除你的node_modules文件夹,运行npm install它将添加缺少的部分到该"dependencies"部分.

  • 这将在你运行`npm i`时删除,而不是编辑你的package-lock.json并将子依赖项添加到那里的"依赖项",将子依赖项添加到你的package.json"dependencies"部分 (34认同)
  • 我创建了一个自动为你做的库:https://github.com/rogeriochaves/npm-force-resolutions (14认同)
  • 它可以工作,但如果我再次运行`npm install`,那么对`package-lock.json`的所有更改都会被恢复,我会得到dep的坏版本. (8认同)
  • 我运行`npm ci`,这不会碰`package-lock.json` (8认同)
  • 我如何指定 git 存储库而不是版本? (3认同)
  • 只要“ npm install”运行一次就可以了。在我的情况下,必须进行编辑,因为嵌套的dep会导致失败。 (2认同)
  • 这对我不起作用。我仍然收到不需要的子依赖版本。 (2认同)
  • @DanielLizik例如,“依赖项”:{“graphql-relay”:{“版本”:“0.6.0”,“已解决”:“git@github.com:LMBernardo/graphql-relay-js.git#6dbd6f3cb0fa901620a85c16c8522d240f4315b4”} } (2认同)

use*_*153 61

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

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

npm install npm-force-resolutions --save-dev
Run Code Online (Sandbox Code Playgroud)

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

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

"resolutions": {
  "your-dependency-name": "1.23.4"
}
Run Code Online (Sandbox Code Playgroud)

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

"preinstall": "npm-force-resolutions",
Run Code Online (Sandbox Code Playgroud)

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

  • 2021 年最新版本的 NPM 是否有内置解决方案?我不想依赖第三方库来做这种事情——操作依赖树。 (6认同)
  • 提示:对“npm install”使用“--save-dev”标志 (3认同)
  • @DaniP。npm 是穷人的依赖管理器,所以我对此表示怀疑 (2认同)
  • 对我来说,预安装命令在 Circle CI 中中断,所以我改用了这个: ```"preinstall": "npm install --package-lock-only --ignore-scripts && npx npm-force-resolutions"```请参阅/sf/answers/4721241941/ (2认同)

Gus*_*Gus 22

对于那些使用纱线的人。

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

毛线对此具有https://yarnpkg.com/lang/zh-CN/docs/selective-version-resolutions/。整齐。

也查看此答案:https : //stackoverflow.com/a/41082766/3051080


Jus*_*rty 10

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

如果您只是对覆盖包的版本号感兴趣,那么这里其他答案中概述的大多数策略都可以很好地工作,但在我们的例子中,我们需要找到一种方法来完全覆盖具有不同包的嵌套 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"
}
Run Code Online (Sandbox Code Playgroud)

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

npm view ansi-html-community dist.tarball --registry=https://registry.npmjs.org/
Run Code Online (Sandbox Code Playgroud)

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

npm view ansi-html-community dist.tarball --registry=https://registry.npmjs.org/
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这真的很有用。我认为通过使用引用覆盖来替换包是可能的,例如“bar”:“$foo”,如最后一个示例中记录的[此处](https://docs.npmjs.com/cli/v8/configuring -npm/package-json#overrides) 但我无法让它工作。但你的解决方案成功了,我会为细节加分。 (3认同)

And*_*dis 10

根据其余的答案,我提供了相同的解决方案,但我显示了 package.json,因为我在放置覆盖的位置和方式上遇到了一些困难。

{
  "name": "my-app",
  "version": "snapshot",
  "scripts": {
    "ng": "ng",
    "build-dev": "ng build --configuration development",
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~14.2.9",
    "@angular/common": "~14.2.9"
    ...
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^14.2.8",
    ....
  },
  "overrides": {  
    "loader-utils@>2.0.0 <3": "2.0.4",
    "loader-utils@>3.0.0 <4": "3.2.1"
  }
}
Run Code Online (Sandbox Code Playgroud)

针对2022年11月“loader-utils”安全漏洞,要求

  • 如果您使用的是 2.X,请使用版本 2.0.4
  • 如果您使用的是 3.X,请使用版本 3.2.1

并验证

  • 添加 package.json 的 override 标签
  • 删除package-lock.json
  • 运行“npm安装”
  • 运行“npm 审核”


归档时间:

查看次数:

107004 次

最近记录:

6 年,3 月 前