【103】Peer Dependencies (同版本依赖)

2023-10-26

原文地址:https://blog.domenic.me/peer-dependencies/

nodejs官网收录了这篇文章,地址是https://nodejs.org/en/blog/npm/peer-dependencies/

作者是 Domenic Denicola ,就职于谷歌Chrome团队。github 上npm开源项目的参与者。

在本文中我把 Peer Dependencies 翻译成了同版本依赖。peer 字典中,除了“仔细看”的意思外,还有“(官阶、等级、地位或功绩)同等的人”的意思。这里结合上下文,应该是版本号相同的意思,所以翻译成同版本依赖。

下面是正文内容:

npm 作为一款包管理器来说,是很优秀的。特别值得一提的是,它可以把子依赖处理得非常好。假如我的包依赖于两个模块:2号版本的 request 和 some-other-library (为了方便举例子,假设另一个模块的名字叫some-other-library),同时 some-other-library 又依赖于 1 号版本的 request ,产生的依赖图看起来像这样:

├── request@2.12.0
└─┬ some-other-library@1.2.3
  └── request@1.9.9

一般来讲,这个结果是非常好的:现在 some-other-library 有了能供它调用的 request 1 号版本的副本,同时不会干扰我的包依赖的request 2号版本的副本。每个人的代码都可以正常工作。

难题:插件

然而,有一个用例会让上文提及的处理方案行不通:插件。即使插件包不一定直接使用宿主包,插件包也往往意味着会被其它的宿主包所用。在 Node.js 开发包生态中,已经有了许多这种模板的例子了:

即使你不精通哪些用例,你也一定能从过去当客户端开发者的时候回忆起 jQuery 插件:你放进页面中的 <script> 标签会把插件连接到 jQuery.prototype ,这方便了以后的维护。

本质上,插件的设计初衷就是给宿主包用的。但更重要的是,插件作者把插件设计成给特定版本的宿主包用。举个例子,我的 chai-as-promised 包的 1.x 和 2.x 版本运行在 chai 的 0.5 版本上,然而 chai-as-promised 3.x 版本却运行在 chai 1.x 版上。或者在更快节奏和更少语义化版本规范支持的 Grunt 插件世界,虽然 grunt-contrib-stylus 0.3.1 版能在 grunt 0.4.0rc4 版上运行,但是 grunt-contrib-stylus 同一个版本不能在 grunt 0.4.0rc5 版上运行,原因竟是新版本的 grunt 删除了一些 API 。

作为一款包管理器,当 npm 安装你的依赖的时候,npm很大一部分工作是管理依赖的版本。但是npm 的普通模式,根据package.json中的配置来使用依赖的哈希值,在碰到插件的时候很明显会运行出错。绝大多数插件从来没有实际依赖宿主包(译者注:这里指插件的代码中有引用宿主包的语句。),比如 grunt 插件从来没有写 require("grunt") 代码。就算插件下载了宿主包作为依赖,那个下载下来的副本也从来不会被使用。因为你的应用使用的插件可能和宿主包不兼容,我们又回到了原点。

甚至对于那些由于宿主包提供了工具API,而可以直接引用宿主包的插件,依然会有问题。在插件包的 package.json 文件中指定宿主包会造成依赖树有宿主包的多个拷贝——而不是你想的那样。举个例子,让我们假设 winston-mail 0.2.3 在其依赖项哈希值中指定”winston”: “0.5.x”,原因在于 winston 0.5.x 是 winston-mail 0.2.3 反复测试的最后一个版本。作为一名应用开发者,因为你想要最后的和最好的版本,所以你查阅了 winston 和 winston-mail 的最后版本,并把版本号放到了你的 package.json 里面,像下面这样:

{
  "dependencies": {
    "winston": "0.6.2",
    "winston-mail": "0.2.3"
  }
}

但是现在,执行 npm install 命令生成了出乎意料的依赖图:

├── winston@0.6.2
└─┬ winston-mail@0.2.3
  └── winston@0.5.11

因为插件使用了不同的Winston API,所以会产生这个不易察觉的安装失败。我愿意留下这个不易察觉的安装失败来给你思考,而不是留下整个主要的应用。

解决方案:同版本依赖(Peer Dependencies)

我们需要一种表现插件及其宿主包之间依赖关系的方法。某种程度上说,“因为我只能运行在1.2.x版本的宿主包中,所以如果你要安装我,请确保使用了兼容的宿主包。”我们把这种关系叫做同版本依赖。

同版本依赖的主意已经被讨论了好几年了。九个月前,在我花了整个周末时间志愿完成了这个功能之后,我最终经历了一个自由(译者注:free指自由软件)的周末,现在npm有了同版本依赖。

特别地,npm 1.2.0 以基础的方式实现了同版本依赖,并在接下来几个新的发布版本不断改善同版本依赖,加入了一些我事实上喜欢的东西。今天 Issac 把 npm 1.2.10 打包进了 Node.js 0.8.19,因此假如你安装了最新版本的 Node,你就已经做好了使用同版本依赖的准备了。

As proof, I present you the results of trying to install jitsu 0.11.6 with npm 1.2.10:
作为证据,我给你看看用 npm 1.2.10 尝试安装 jitsu 0.11.6 的结果。

npm ERR! peerinvalid The package flatiron does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer flatiron-cli-config@0.1.3 wants flatiron@~0.1.9
npm ERR! peerinvalid Peer flatiron-cli-users@0.1.4 wants flatiron@~0.3.0

如你所见,jitsu依赖于两个和 Flatiron 相关的包,这些包同版本依赖于 Flatiron 的两个冲突的版本。好东西npm已经积极地帮助我们找出了冲突,因此这个错误能在0.11.7版本被修复!

使用同版本依赖

同版本依赖非常易于使用。当写一个插件的时候,弄明白宿主包的哪一个版本是你要做同版本依赖的,然后把宿主包的版本加入 package.json中。

{
  "name": "chai-as-promised",
  "peerDependencies": {
    "chai": "1.x"
  }
}

现在当安装chai-as-promised的时候,chai 报会跟着一块安装。如果你以后尝试安装只兼容 Chai 0.x 版本的 Chai 插件,你会得到一个错误。这非常好!

一条建议:同版本依赖的必要条件,不同于正常依赖的必要条件,应该更宽容些。你不应该把你的同版本依赖锁定到某个特定的补丁版本号上。假如仅仅因为 Chai 插件的作者们懒惰并且没有花时间弄清楚 Chai 插件兼容的 Chai 宿主包的最小版本,就会让一个Chai 插件同版本依赖于 Chai 1.4.1,另一个Chai插件同版本依赖于 Chai 1.5.0 ,这样同版本依赖就会用起来很烦人。

确定同版本依赖的必要条件的最好方法是切实遵守语义化版本控制规范。我们先假定只有宿主包的主要版本中的更改会破坏你的插件。因此如果你的插件兼容宿主包 1.x 中的每个细分版本,那么就用 "~1.0""1.x" 来表达这个意思。如果你依赖于 1.5.2 版本实现的特性,使用 ">= 1.5.2 < 2"

从现在开始,使用同版本依赖吧!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【103】Peer Dependencies (同版本依赖) 的相关文章

随机推荐

  • 计算机无法识别荣耀9,华为荣耀9连接不上电脑端华为手机助手怎么处理?

    如果手机无法连接华为手机助手 可通过以下步骤来尝试解决 步骤一 请确认USB线连接是否正常 若手机通知栏中没有显示USB已连接的提示 则可能是USB线连接不正常 手机能充电不能说明USB线是完全连接正常 比如部分USB线仅支持充电不支持数据
  • 独家

    随机森林 概述 当变量的数量非常庞大时 你将采取什么方法来处理数据 通常情况下 当问题非常庞杂时 我们需要一群专家而不是一个专家来解决问题 例如Linux 它是一个非常复杂的系统 因此需要成百上千的专家来搭建 以此类推 我们能否将许多专家的
  • 将线程pid转成16进制_如何使用jstack分析线程状态

    背景 记得前段时间 同事说他们测试环境的服务器cpu使用率一直处于100 本地又没有什么接口调用 为什么会这样 cpu使用率居高不下 自然是有某些线程一直占用着cpu资源 那又如何查看占用cpu较高的线程 当然一个正常的程序员不会写出上述代
  • Spring Cloud中的Ribbon的实现和使用

    Spring Cloud Ribbon 是 Spring Cloud 生态系统中的一个负载均衡客户端 它可以轻松地与其他 Spring Cloud 组件集成 提供负载均衡的方式来访问后端服务 下面介绍 Spring Cloud Ribbon
  • 如何进行远程调试(remote debug)。

    场景 scenario 本地机器 A 重现不了问题 其他机器或其他系统 B 可以重现问题 而重现问题的机器没有装VS调试工具 在开发本地机器中拷贝远程调试工具 以VS 2015 为例 将C Program Files x86 Microso
  • yum错误:Invalid configuration value: failovermethod=priority in /etc/yum.repos.d/CentOS-Epel.repo;

    错误描述 yum install y yum utils device mapper persistent data lvm2 Invalid configuration value failovermethod priority in e
  • 解析优化机器人课程体系与教学策略

    依据 基础教育信息技术课程标准 制定机器人教育课程标准 将机器人教育课程纳入新的课程体系 对现有机器人教育教材进行重新规划和修订 提高机器人教育在中小学阶段课时的比例 同时保证实践课的课时比例 加强学生的动手能力 保证教学质量 除此 还要保
  • 请尽快报名参加Imagine Cup 微软“创新杯”全球学生大赛

    微软Imagine Cup 2013大赛报名即将截止 截止报名时间是2013年1月31日 请各大高校抓紧时间报名参加 CSDN高校俱乐部校区将选出1个校区一等奖 10个校区二等奖 校区一等奖可直接参加中国区半决赛 团队成员还可获得CSDN高
  • VS构建项目报错信息及解决办法04

    报错信息及解决7 报错信息详情 error LNK2001 无法解析的外部符号 symbol 原因 编译后的代码引用或调用符号 该符号未在链接器搜索的任何库或对象文件中定义 什么是未解析的外部符号 符号 是函数或全局变量的内部名称 它是在已
  • 【算法】最优服务次序问题(贪心算法)

    设有n 个顾客同时等待一项服务 顾客i需要的服务时间为 t i 1 lt i lt n 应如何安排n个顾客的服务次序才能使平均等待时间达到最小 平均等待时间是n 个顾客等待服务时间的总和除以n 输入格式 第一行是正整数n 1
  • 归档的概念和用法

    归档的概念和用法 概念 对象归档是指将对象写入文件保存在硬盘的文件内 当在次打开程序时 可以还原这些对象 也可以称为对象序列化 对象持外化 数据持久化的方式 1 gt NSKeyedArchiver 对象归档 2 gt NSUserDefa
  • 回味2022

    回味2022 1 前言 2 过去的十二个月 3 我期望的2023 1 前言 2021年写给自己的总结 回味2021 一年又一年飞逝的光阴 我想唯有时间留给人的印象最为深刻吧 春去秋来 四季轮回间都是时光的印记 2022年12月30日 25岁
  • pycocotools报错 if type(resFile) == str or type(resFile) == unicode: NameError: name ‘unicode‘ is

    Q pycocotools报错 if type resFile str or type resFile unicode NameError name unicode is not defined A pycocotools与python版本
  • Springboot定义Controller接口的这些方式你肯定不知道

    环境 Springboot2 4 11 概述 当一个请求过来后Spring是如何进行处理的 下面简单的罗列下请个的过程中核心组件 SpringMVC处理的流程 DispatcherServlet 所有请求的入口 HandlerMapping
  • unity获取子物体个数、获取别的脚本的参数、获取脚本名、查找显示的物体、物体的显示和隐藏

    获取子物体个数 我有这么一个层级 我要获取levelSelectPanel里的levelSelectButton个数 于是 在脚本里先定义一个GameObject 用于接受面板输入进来的levelSelectPanel是哪一个 public
  • Python+Vue计算机毕业设计Vue的小区物业管理网站gb99s(源码+程序+LW+部署)

    该项目含有源码 文档 程序 数据库 配套开发软件 软件安装教程 项目运行环境配置 Python3 7 7 Django Mysql5 7 pip list HBuilderX Vscode也行 Vue Pychram社区版 项目技术 Dja
  • TypeScript学习(四):对象的定义及使用

    前面我们说到了数据类型 像什么布尔类型 数值类型 字符串类型等等 在开发中 我们还会遇到很多像对象 数组 函数等类型 那么在typescript中是怎么定义这些类型的 对象 object 我们先介绍下在JavaScript中式怎么定义对象的
  • 小智AI ChatGPT拓展人工智能应用的新可能

    人工智能 AI 技术是当今世界上最受关注的领域之一 随着越来越多的数据被收集 处理和分析 人们对AI的期望也在不断提高 AI的应用范围已经不再局限于科学研究和工业生产 而是逐渐渗透到各个领域 如医疗保健 金融 农业等 本文将探讨ChatGP
  • “negative event times encountered; not permitted for Cox family“

    not permitted for Cox family 搞了好久 才发现生存时间里面有0值 所以必须删除0 基于Lasso回归筛选变量构建Cox模型并绘制Nomogram 研究背景 本章是基于Lasso回归筛选变量后 构建Cox回归临床预
  • 【103】Peer Dependencies (同版本依赖)

    原文地址 https blog domenic me peer dependencies nodejs官网收录了这篇文章 地址是https nodejs org en blog npm peer dependencies 作者是 Domen