NodeJS 项目中的 PeerDependencies 是什么?

2025-06-08

NodeJS 项目中的 PeerDependencies 是什么?

PeerDependencies,当我在终端中收到如下所示的 PeerDependency 警告时,这个术语至少对我来说是令人困惑的:

替代文本

最近,一个 Node 包中发生了一起恶意代码攻击事件,该攻击大量涉及 PeerDependencies 的概念,这最终激起了我对这个主题的好奇,促使我开始深入研究 PeerDependencies 的工作原理。在这篇博文中,我将记录我关于 NodeJS PeerDependencies 的一些发现,希望能帮助您更好地理解这个主题。

"What are peer dependencies"当然,用谷歌搜索确实能找到一些结果。然而,谷歌返回的主要参考资料中,没有一个能让我以满意的方式理解 PeerDependencies。一段时间后,我找到了一个Stackoverflow 页面,其中包含Stijn De Witt对 PeerDependencies 的精彩解释。他的解释非常接近于让我理解 PeerDependencies 基础知识,并让我在脑海中产生一些“啊哈!”的瞬间(谢谢 Stijn!)。但不知何故,由于我更倾向于视觉学习,Stijn 的“文本驱动” Stackoverflow 解释并没有让我在理解 PeerDependencies 方面获得那种“最后一英里”的满足感。因此,我根据他的解释绘制了一些代码(您可以在下面看到引用),突然间,我的想法变得清晰起来。

有什么问题?

先声明一下:在接下来的示例中,JillsModule这将是整个流程中最棘手的部分(随后是 PeerDependency)。因此,我在使用时添加了虚构的版本号附加(@1.0、@2.0)。

假设我们正在构建OurCoolProject并使用JacksModuleJillsModule@2.0。同时假设JacksModule也依赖于 JillsModule,但依赖于不同的版本,比如JillsModule@1.0。只要这两个版本不相容,就不会有问题。 的JacksModule使用JillsModule仅仅是一个实现细节。我们进行了JillsModule两次打包(因为代码使用了两个不同的版本,但彼此之间没有关联!),但当我们获得稳定的开箱即用软件时,这只是一个小小的代价。

在代码中这意味着

// OurCoolProcject.js

import JacksModule from 'jacksmodule';
import JillsModule(@2.0) from 'jillsmodule(@2.0)';

const OurCoolProcject = () => {
    // do some stuff with JacksModule
    // do some stuff with JillsModule(@2.0). stuff won't break as we have the compatible @2.0 version of JillsModule available in this scope.
}

export default OurCoolProject;
Enter fullscreen mode Exit fullscreen mode
// jacksmodule.js (an npm module)

import JillsModule(@1.0) from 'jillsmodule(@1.0)';

const JacksModule = () => {
    // do some stuff with JillsModule(@1.0). stuff won't break as we have the compatible @1.0 version of JillsModule available in this scope.
}

export default JacksModule;
Enter fullscreen mode Exit fullscreen mode

但接下来这种依赖关系会变得更加棘手。

现在假设以某种方式JacksModule暴露了它的依赖关系JillsModuleobject instanceof JillsClass例如,它接受一个……如果我们创建一个new JillsClass使用该库 2.0 版本的 ,并将其传递给jacksFunction(我们知道,这不包括 1.0 版本!),会发生什么?一切都会乱套!像 这样的简单事情jillsObject instanceof JillsClass会突然返回false,因为jillsObject实际上是另一个 的实例JillsClass,也就是 2.0 版本。

在代码中这意味着这样:

// OurCoolProcject.js

import jacksFunction from 'jacksmodule';
import JillsModule(@2.0) from 'jillsmodule(@2.0)'; // node resolves to OUR dependency of JillsModule which is 2.0!

const OurCoolProcject = () => {    
    const jillsObject = new JillsModule(@2.0).JillsClass;

    // next the beginning of all evil, we'll pass a jillsObject of version 2.0
    // to jacksFunction (that would expect jillsObject of version 1.0 🤦‍♀️)
    jacksFunction(jillsObject); 
}

export default OurCoolProject;
Enter fullscreen mode Exit fullscreen mode
// jacksmodule.js (an npm module)

import JillsModule(@1.0) from 'jillsmodule(@1.0)';

const jacksFunction = (jillsObject) => {
    // make sure jillsObject is compatible for further usage in this function
    const jillsObjectRocks = jillsObject instanceOf JillsModule(@1.0).JillsClass;
            // └─> 🔥🔥🔥 `jillsObjectRocks` will be a big, fat FALSE
            // as the JillsModule dependencies actively used in this function and
            // passed to this function differ in versions (1.0 vs. 2.0) 🤦‍♀️
    ...
}

export default jacksFunction;
Enter fullscreen mode Exit fullscreen mode

你注意到这里发生了什么吗?jacksFunction收到一个不兼容的错误jillsObject,因为该对象是基于 JillsModule(2.0) 构建的,而不是基于 JillsModule(1.0)JacksModule构建的。到目前为止,这仅仅表明了在最坏的情况下会导致软件无法正常工作的问题。

PeerDependencies 如何解决这个问题

幸运的是,npm 内置了一些智能机制来解决这个问题。如果 JacksModule 将 JillsModule(@1.0) 声明为 PeerDependency,npm 会在安装项目依赖项时向用户发出警告。因此,JacksModulepackage.json应该包含以下声明:

{
  "name": "JacksModule",
  ...
  "peerDependencies": {
    "JillsModule": "1.x"
  },
  ...
}
Enter fullscreen mode Exit fullscreen mode

因此,npm 的 PeerDepenedency 智能基本上会触发控制台输出,向我们的开发人员发出警告,内容如下:

嘿,我是 JacksModule。我来告诉你:我需要这个特定的 JillsModule 包,但我真正需要的是属于我的 JacksModule 项目并列在我的 package.json 文件中的版本。所以请确保它已安装,并且不是你可能在应用程序的其他地方安装的、供自己使用的 JillsModule 的其他版本。

所以,最终——进一步思考——依赖需要 PeerDependencies 的 npm 包可能会很棘手。假设你需要一个新版本的包 X 供应用程序中单独使用,而你应用程序中使用的另一个依赖项对另一个版本的包 X 也具有 PeerDependency,那么这可能会引发问题。如果出现这种情况——在最坏的情况下还会导致软件出现问题——你就得自己决定使用哪个包,或者哪些代码可能需要重构才能满足所有需求。

我希望这些解释和代码示例能够帮助你理解,并弥补你之前关于 PeerDependencies 的思考空白。如果你有任何疑问或想提出一些文章优化建议,请随时联系我或留言。

这篇文章最初发布于此处

鏂囩珷鏉ユ簮锛�https://dev.to/btdev/what-are-those-peerdepenedcies-in-a-nodejs-project-51jo
PREV
React 备忘单
NEXT
通过 Advent Of Code 学习 Rust - 第一部分