英文:
How does NPM manage node_modules Transitive Dependencies?
问题
Q1 - 包 A
的哪个版本会被安装?包 A
会被安装在哪里,是在 MyApp
的 node_modules
文件夹中,还是在 B
的 node_modules
中,或者在 C
的 node_modules
中?
Q2 - 我的想法是,NPM 将在 MyApp
的 node_modules
文件夹中安装 A (1.0)
,并在包 C
的 node_modules
中安装 A (2.0)
。
Q3 - 但如果我只想要安装 一个 全局的 A (2.0)
副本,应该怎么做才能让 NPM 这样做?
英文:
Let’s say I create an app called MyApp
and it depends on package A
(version 1.0) and package B
which depends on package C
which in turn depends on package A
(version 2.0):
MyApp
- A @ 1.0
- B
A
- (no dependencies in whichever version)
B
- C
C
- A @ 2.0
My question is.
Q1 - Which version of the package A
will be installed? Will package A get installed or MyApp
’s node_modules, B
’s node_modules or C
’s node_modules?
Q2 - My thinking is, NPM will install A (1.0)
in MyApp
's node_modules folder and install A (2.0)
on package C
's node_modules.
Q3 - But if I just want one copy of A (2.0)
to be installed globally, what should I do to make NPM do in this way?
答案1
得分: 1
根据 https://docs.npmjs.com/cli/v6/configuring-npm/folders#cycles-conflicts-and-folder-parsimony 中的文档,你的Q2假设是正确的,这也回答了Q1。
在每个阶段,如果一个包已经安装在祖先的
node_modules
文件夹中,那么它不会在当前位置被安装。
为了说明,让我们修改你的示例,将 A (1.0)
也添加为 B
的依赖项:
MyApp
- A @ 1.0
- B
A
- (在任何版本中都没有依赖关系)
B
- A @ 1.0 (仅用于说明)
- C
C
- A @ 2.0
结果的目录树和相应的版本(不包含在文件夹名称中)应该如下所示:
MyApp/node_modules/A (@ 1.0)
MyApp/node_modules/B
MyApp/node_modules/B/node_modules/C
MyApp/node_modules/B/node_modules/C/node_modules/A (@ 2.0)
注意:在这里没有
MyApp/node_modules/B/node_modules/A (@ 1.0)
的存在,因为它已经在更高的位置,位于 MyApp
下面。
(附注:如果 B
不依赖于 A (1.0)
,根据文档,我不完全确定在这种假设情况下 A (@ 2.0)
是否会出现在更高一级(在 B
下面),因为 B
将是第一个没有版本不匹配的最顶层的祖先,尽管在这种假设情况下 B
并没有依赖于 A
。这将允许所有的“兄弟”共享同一个模块,而不会与根级别的依赖项发生冲突。)
至于Q3的答案很简单(我猜你所说的“全局”是指 MyApp
(根)模块,而不是系统范围的模块):由于你决定了 MyApp
的依赖关系,如果应用程序可以使用 A (2.0)
,只需将该依赖项的版本从 1.0
升级并进行更新。之后只会有
MyApp/node_modules/A (@ 2.0)
而不是 .. (@ 1.0)
,前者
MyApp/node_modules/B/node_modules/C/node_modules/A (@ 2.0)
将被删除。
如果情况相反(C
依赖于 旧的 A (1.0)
而不是新的 2.0
),那么除非更改这些模块,否则我没有明确的答案,除非您只需让 C
的作者解锁或升级到 A (2.0)
,即我认为在不更改这些模块的情况下是不可能的。
英文:
Considering solely documentation at https://docs.npmjs.com/cli/v6/configuring-npm/folders#cycles-conflicts-and-folder-parsimony, your Q2 assumptions are right, what also answers Q1.
> […] at every stage, if a package is already installed in an ancestor node_modules
folder, then it is not installed at the current location.
For illustration, let's modify your example and add A (1.0)
also as a dependency of B
:
MyApp
- A @ 1.0
- B
A
- (no dependencies in whichever version)
B
- A @ 1.0 (added for illustration)
- C
C
- A @ 2.0
Resulting directory tree with respective versions (that are NOT part of the folder names) should then look like this:
MyApp/node_modules/A (@ 1.0)
MyApp/node_modules/B
MyApp/node_modules/B/node_modules/C
MyApp/node_modules/B/node_modules/C/node_modules/A (@ 2.0)
NB: there is NO
MyApp/node_modules/B/node_modules/A (@ 1.0)
present there, since it is already present higher, under MyApp
.
(Side note: in case B
would not depend on A (1.0)
, from the docs I am not completely sure, whether the A (@ 2.0)
wouldn't appear one level higher (under B
) instead, as B
would be the first top-most ancestor without version mismatch, even though it was not B
's dependency at all in this hypothetical case. This would allow all "siblings" share same module without colliding with root level dependency.)
As for Q3 the answer is simple (I guess by "global" you mean MyApp
(root) module, not system-wide modules): since you dictate MyApp
's dependencies, if the app can work with A (2.0)
, just bump up that dependency version from 1.0
and do the update. After that there should only be
MyApp/node_modules/A (@ 2.0)
instead of .. (@ 1.0)
and the former
MyApp/node_modules/B/node_modules/C/node_modules/A (@ 2.0)
should be gone.
If it was other way round (C
would depend on older A (1.0)
instead of newer 2.0
) then I don't have a clear answer, besides you would just have to make C
author unlock or bump-up dependency to A (2.0)
, i.e. I don't think it is possible without altering those modules.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论