简体   繁体   English

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

[英]How do I override nested NPM dependency versions?

I would like to use the grunt-contrib-jasmine NPM package. It has various dependencies.我想使用grunt-contrib-jasmine NPM package。它有各种依赖项。 Part of the dependency graph looks like this:部分依赖图如下所示:

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

Unfortunately, there's a bug in this version phantomjs which prevents it from installing correctly on Mac OS X. This is fixed in the latest version.不幸的是,这个版本的phantomjs中有一个错误,导致它无法在 Mac OS X 上正确安装。这在最新版本中已修复。

How can I get grunt-lib-phantomjs to use a newer version of phantomjs ?我怎样才能让grunt-lib-phantomjs使用更新版本的phantomjs

Some additional context:一些额外的背景:

You can use npm shrinkwrap functionality, in order to override any dependency or sub-dependency.您可以使用npm 收缩包装功能,以覆盖任何依赖或子依赖。

I've just done this in a grunt project of ours.我刚刚在我们的一个grunt的项目中做到了这一点。 We needed a newer version of connect, since 2.7.3 .2.7.3开始,我们需要更新版本的连接。 was causing trouble for us.给我们带来了麻烦。 So I created a file named npm-shrinkwrap.json :所以我创建了一个名为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 should automatically pick it up while doing the install for the project. npm应该在为项目安装时自动选择它。

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

As of npm cli v8.3.0 (2021-12-09) this can be solved using the overrides field of package.json .从 npm cli v8.3.0 (2021-12-09) 开始,这可以使用 package.json 的overrides字段来解决 As described in StriplingWarrior's answerStriplingWarrior 的回答中所述

For example, the project has typescript version 4.6.2 as direct development dependency and awesome-typescript-loader that uses old version 2.7 of typescript .例如,该项目具有typescript版本4.6.2作为直接开发依赖项和使用旧版本2.7 typescript awesome-typescript-loader Here is how you can tell npm to use version 4.6.2 of typescript for awesome-typescript-loader :以下是如何告诉npm使用typescript4.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"
    }
  }
}

If you don't use typescript as direct development dependency, then you have to write 4.6.2 instead of $typescript in overrides section:如果您不使用typescript作为直接开发依赖项,那么您必须在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"
    }
  }
}

Same overrides can be used for both dependencies and devDependencies . dependencies项和devDependencies都可以使用相同的overrides


If you're using npm version >5 but <8.3.0: edit your package-lock.json : remove the library from "requires" section and add it under "dependencies".如果您使用 npm 版本 >5 但 <8.3.0:编辑您的package-lock.json :从"requires"部分删除库并将其添加到“依赖项”下。

For example, you want deglob package to use glob package version 3.2.11 instead of its current one.例如,您希望deglob package 使用glob package 版本3.2.11而不是当前版本。 You open package-lock.json and see:打开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"
  }
},

Remove "glob": "7.1.2", from "requires" , add "dependencies" with proper version:"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"
    }
  }
},

Now remove your node_modules folder, run npm ci (or npm install for old version of node/npm) and it will add missing parts to the "dependencies" section.现在删除你的node_modules文件夹,运行npm ci (或npm install for old version of node/npm),它会将缺失的部分添加到"dependencies"部分。


As of NPM v8.3 , the correct way to deal with this is via the overrides section of your package.json file.从 NPM v8.3开始,处理此问题的正确方法是通过package.json文件的overrides部分。

If you need to make specific changes to dependencies of your dependencies, for example replacing the version of a dependency with a known security issue, replacing an existing dependency with a fork, or making sure that the same version of a package is used everywhere, then you may add an override.如果您需要对依赖项的依赖项进行特定更改,例如用已知安全问题替换依赖项的版本,用分叉替换现有依赖项,或者确保在任何地方都使用相同版本的 package,那么你可以添加一个覆盖。

Overrides provide a way to replace a package in your dependency tree with another version, or another package entirely.覆盖提供了一种将依赖关系树中的 package 替换为另一个版本或完全替换为另一个 package 的方法。 These changes can be scoped as specific or as vague as desired.这些更改的范围可以根据需要具体或模糊。

To make sure the package foo is always installed as version 1.0.0 no matter what version your dependencies rely on:为了确保 package foo 始终安装为 1.0.0 版本,无论您的依赖项依赖什么版本:

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

There are a variety of other, more nuanced configurations allowing you to only override a package when it's a dependency of a particular package hierarchy.还有许多其他更细微的配置,允许您仅在 package 层次结构的依赖项时覆盖 package。 For more details, check out https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides有关更多详细信息,请查看https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides

The only solution that worked for me (node 12.x, npm 6.x) was using npm-force-resolutions developed by @Rogerio Chaves .唯一对我有用的解决方案(节点 12.x,npm 6.x)是使用由@Rogerio Chaves开发的npm-force-resolutions

First, install it by:首先,通过以下方式安装它:

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

You can add --ignore-scripts if some broken transitive dependency scripts are blocking you from installing anything.如果某些损坏的传递依赖脚本阻止您安装任何东西,您可以添加--ignore-scripts

Then in package.json define what dependency should be overridden (you must set exact version number ):然后在package.json中定义应该覆盖的依赖项(您必须设置确切的版本号):

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

and in "scripts" section add new preinstall entry:并在"scripts"部分添加新的预安装条目:

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

Now, npm install will apply changes and force your-dependency-name to be at version 1.23.4 for all dependencies.现在, npm install将应用更改并强制your-dependency-name为所有依赖项的版本1.23.4

For those using yarn.对于那些使用纱线的人。

I tried using npm shrinkwrap until I discovered the yarn cli ignored my npm-shrinkwrap.json file.我尝试使用 npm 收缩包装,直到我发现纱线 cli 忽略了我的 npm-shrinkwrap.json 文件。

Yarn hashttps://yarnpkg.com/lang/en/docs/selective-version-resolutions/ for this.为此,Yarn 有https://yarnpkg.com/lang/en/docs/selective-version-resolutions/ Neat.整洁的。

Check out this answer too: https://stackoverflow.com/a/41082766/3051080也看看这个答案: https://stackoverflow.com/a/41082766/3051080

Nested replacement with an entirely different package使用完全不同的 package 进行嵌套替换

Most of the strategies outlined in the other answers here work well if you are just interested in overriding the package's version number, but in our case, we needed to find a way to override a nested npm sub-dependency with a different package altogether.如果您只是对覆盖包的版本号感兴趣,那么此处其他答案中概述的大多数策略都可以很好地工作,但在我们的例子中,我们需要找到一种方法来覆盖嵌套的 npm 子依赖项,并完全使用不同的 package For details on why you would ever want to do this, please refer to the following question:有关您为什么要这样做的详细信息,请参阅以下问题:

How to override a nested npm sub-dependency with a different package altogether (not just different package version number)? 如何完全覆盖具有不同 package 的嵌套 npm 子依赖项(不仅仅是不同的 package 版本号)?

Specify the tarball directly直接指定tarball

For nested replacement of a package with an entirely different package using the npm-force-resolutions strategy that others have mentioned, you just need to provide a link to the tarball where you would normally specify the overriding version number.对于使用其他人提到的npm-force-resolutions策略将 package 嵌套替换为完全不同的 package ,您只需提供指向通常指定覆盖版本号的 tarball 的链接。

As an example, for the case of replacing the vulnerable package, ansi-html , with the fixed fork of this package, ansi-html-community , your resolutions section of package.json should look like this: As an example, for the case of replacing the vulnerable package, ansi-html , with the fixed fork of this package, ansi-html-community , your resolutions section of package.json should look like this:

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

To find the link to the tarball, use the following command, modifying your registry as necessary:要找到 tarball 的链接,请使用以下命令,根据需要修改您的注册表:

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

Also, note that for npm-force-resolutions to work when you run npm install , you will need a preinstall entry under the scripts section of package.json :另外,请注意,当您运行npm install时,要使npm-force-resolutions起作用,您需要在package.jsonscripts部分下的preinstall条目:

  "scripts": {
    "preinstall": "npx npm-force-resolutions"
  }

I had an issue where one of the nested dependency had an npm audit vulnerability, but I still wanted to maintain the parent dependency version.我遇到了一个问题,其中一个嵌套依赖项存在 npm 审计漏洞,但我仍然想维护父依赖项版本。 the npm shrinkwrap solution didn't work for me, so what I did to override the nested dependency version: npm 收缩包装解决方案对我不起作用,所以我做了什么来覆盖嵌套的依赖版本:

  1. Remove the nested dependency under the 'requires' section in package-lock.json删除 package-lock.json 中“requires”部分下的嵌套依赖项
  2. Add the updated dependency under DevDependencies in package.json, so that modules that require it will still be able to access it.在 package.json 中的 DevDependencies 下添加更新的依赖项,以便需要它的模块仍然能够访问它。
  3. npm i npm i

@user11153 's answer worked for me locally, but when trying to do a clean install (aka deleting node_modules ), I would get: @user11153 的答案在本地对我有用,但是在尝试进行全新安装(又名删除node_modules )时,我会得到:

npm-force-resolutions: command not found

I had to update the preinstall script to be:我必须将preinstall脚本更新为:

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

Which ensures that npm-force-resolutions package is installed before attempting to run it.这可确保在尝试运行之前安装npm-force-resolutions package。

That being said, if you're able to use yarn instead, I would do that and then use @Gus 's answer.话虽这么说,如果您能够改用纱线,我会这样做,然后使用@Gus 的答案。

I was about to go down the npm-force-resolutions route but it seems that simply including the dependency in my own package.json fixed the problem for me.我正要在npm-force-resolutions路线上进行 go ,但似乎只需将依赖项包含在我自己的package.json中即可解决我的问题。

I believe this worked in my case because the original dependency allows for patch versions of the dependency in question that I wanted to update.我相信这对我来说是可行的,因为原始依赖项允许我想要更新的相关依赖项的补丁版本。 Thus by manually including a newer version it still fulfilled the dependency of the original dependency and will use the one I've manually added.因此,通过手动包含一个较新的版本,它仍然满足原始依赖项的依赖项,并将使用我手动添加的那个。

Example例子

Problem问题

I need to update plyr to version 3.6.9 from 3.6.8我需要将plyr3.6.8更新到版本3.6.9

Mine

package.json

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

React Plyr反应 Plyr

package.json

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

Notice for the plyr dependency it starts with ^ this means it can accept any minor patches.注意它以^开头的plyr依赖项,这意味着它可以接受任何小补丁。 You can learn more about that here:您可以在此处了解更多信息:

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

Updating Mine更新我的

This updates the plyr dependency from my package.json .这更新了我的package.jsonplyr依赖项。

package.json

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

I found a solution that worked for me. 我找到了对我有用的解决方案。

So. 所以。 First edit your npm-shrinkwrap.json file as recommended all others solutions. 首先按照所有其他建议的解决方案编辑npm-shrinkwrap.json文件。

Then, (on Windows): 然后,(在Windows上):

  • Right click on 'npm-shrinkwrap.json' file 右键单击“ npm-shrinkwrap.json”文件
  • Properties 性质
  • Under Attributes select 'Read-Only'. 在属性下,选择“只读”。 This will prevent npm to modify the mpn-shrinkwrap.json file. 这将阻止npm修改mpn-shrinkwrap.json文件。

The other proposed solutions are good enough if you are making the 'npm install' operation just once. 如果您仅执行一次“ npm install”操作,那么其他建议的解决方案就足够了。 But after the first 'npm install' the file 'npm-shrinkwrap.json' is modified again as before your modification. 但是,在第一次“ npm安装”之后,文件“ npm-shrinkwrap.json”会像修改之前一样再次被修改。

Based on the rest of the answers, I provide the same solution, but I display the package.json, as I struggled a little bit on where to place the override and how.基于 rest 的答案,我提供了相同的解决方案,但我显示了 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"
  }
}

For November 2022 "loader-utils" security vulnerability, it was requested to针对2022年11月的“loader-utils”安全漏洞,要求

  • use the version 2.0.4, if you are in the 2.X使用版本 2.0.4,如果你在 2.X
  • use the version 3.2.1, if you are in the 3.X使用版本 3.2.1,如果你在 3.X

And to verify并验证

  • add the package.json the override tag添加 package.json 覆盖标签
  • delete the package-lock.json删除 package-lock.json
  • run "npm install"运行“npm 安装”
  • run "npm audit"运行“npm 审计”

I would like to use the grunt-contrib-jasmine NPM package.我想使用grunt-contrib-jasmine NPM软件包。 It has various dependencies.它具有各种依赖性。 Part of the dependency graph looks like this:依赖关系图的一部分看起来像这样:

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

Unfortunately, there's a bug in this version phantomjs which prevents it from installing correctly on Mac OS X. This is fixed in the latest version.不幸的是,此版本的phantomjs存在一个错误,导致它无法在Mac OS X上正确安装。此问题已在最新版本中修复。

How can I get grunt-lib-phantomjs to use a newer version of phantomjs ?如何获得grunt-lib-phantomjs以使用较新版本的phantomjs

Some additional context:一些其他上下文:

Run this first先运行这个

npm i -D @types/eslint@8.4.3

it will solve the issue它将解决问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM