3

抽象地说,我对提供的版本没问题dependency-B,由于dependency-A.

  "dependencies": {
    "dependency-A": "x.y.z",
   }
$> npm ls --depth=1
├─┬ dependency-A@x.y.z
│ ├── dependency-B@x.y.z

所以当我 时require('dependency-B'),我会期待A 的依赖。
我正在使用该库中的 root 函数,事实上,如果dependency-A版本有问题,我想与它保持一致并使用它使用的相同版本。

如果dependency-B在依赖项中列出,将安装一个全新的包。

  "dependencies": {
    "dependency-A": "x.y.z",
    "dependency-B": "a.b.c",
   }
$> npm ls --depth=1
├─┬ dependency-A@x.y.z
│ ├── dependency-B@x.y.z
│ ├── ...
├─┬ dependency-B@a.b.c

我很想不列出dependency-B我的依赖项。我应该避免这种做法吗?依赖我的主要依赖安装的对等版本不行吗?


如果这是一个布拉德的做法,我怎么能告诉 npm 给我它由另一个包安装的完全相同的版本?

  "dependencies": {
    "dependency-A": "x.y.z",
    "dependency-B": "~try the one that is installing dependency-A~",
   }
4

1 回答 1

2

tl;dr:您应该始终拥有在自己的dependencies对象中使用的所有依赖项,因为包管理器的一致实现不需要让您访问依赖项的依赖项。

这是一个有趣的问题,我可以想到您可能会遇到的两种情况:

  1. 由于您自己的一系列原因,您的包和独立dependency-A使用dependency-B,您根本不在乎使用哪个版本。
  2. 您需要通过创建 B 的对象或接收 A 创建的 B 的对象dependency-B来与 进行交互。dependency-A

场景一:独立使用

如果您和您的依赖项需要相同的包但不需要共享任何内容,Node 为您提供了惊人的能力,即通过在package.json包和库中指定不同版本,在不同地方使用同一包的不同版本。这是 Node 模块系统的优势之一。

但是,您的情况是您不关心软件包的实际版本(这让我认为这不是您的情况)。特别是,您想知道是否最好不要自己定义任何内容,package.version而让 Node 找到您的依赖项的依赖项。

最后一种情况是可能的,因为您正在使用npm,并且npm做了一件特定的事情:它扁平化模块树以消除重复数据包,也就是说,同一版本可以满足的多个依赖项规范在最后,使用完全相同的版本。这会减少模块树的大小和深度,但会产生意想不到的后果,即您现在可以访问尚未指定为依赖项的包,只是因为它们安装在您node_modules的目录中是为了进行重复数据删除。

不过,这不是唯一可能的策略pnpm,另一个包管理器使用符号链接来实现相同的目标。我不会详细介绍,而是pnpm将所有依赖项安装在不同的系统范围(或用户特定)目录中,然后从您的node_modules(以及依赖项自己的node_modules)符号链接到该文件夹​​中的适当位置。这不仅实现了项目重复数据删除,还实现了系统范围的重复数据删除,因为使用特定包版本的所有项目都将使用相同的安装。然而,这个系统的结果是你“失去”了在你自己的包中使用依赖项的依赖项的能力,因为它们不再物理上位于node_modules.

除此之外,您不关心他们使用的版本的想法。几乎从来没有这种情况,因为语义版本控制的重点是避免或包含由于依赖版本升级而导致的损坏。您不关心您现在使用的版本,但是如果该软件包在您的依赖项中升级到不同的主要版本,您的软件包可能会意外损坏。

总之,不定义无论如何都要使用的依赖项是一种不好的做法,因为它会阻止其他开发人员在不同的包管理器中使用您的包,并且因为它会使您面临无法预料的破坏要妥善管理。

场景 2:依赖使用

鉴于您对问题的描述,更有可能的情况是,在您使用 的某个时刻dependency-A,它要么要求某些东西,要么从dependency-B. 在这种情况下,希望两者都使用相同的或至少兼容的版本,以便所有关于正在交换的对象形状的假设都成立。

指定这种情况的正确方法是显式声明dependency-Bdependency-A. 如果不是这种情况,那么它们就是不正确的,如果可能的话,您绝对应该在问题中提出这一点。作为一种解决方法,您可以只声明与他们相同的版本,并注意他们的版本升级可能导致的损坏。不自己定义任何东西package.json可能会遇到与场景 1 中相同的问题。

但是,另一种可能性是您甚至不需要require该依赖项。可能是他们希望您传递数据、函数、对象或任何将进一步传递给 的东西dependency-b,但以某种方式使您不必直接与之交互dependency-B。在这种情况下,他们实质上是将 B 的 API 的一部分合并到自己的 API 中,因此任何来自dependency-B的重大更改也应该导致dependency-A. 这可以保护您免受意外损坏,避免您必须定义您的任何内容,package.json并意味着您是安全的。

于 2020-12-03T12:47:21.163 回答