5.3 依赖类型深度区分


5.3 依赖类型深度区分

本节摘要:清单文件里的依赖字段不是一个,而是五个:dependencies、devDependencies、peerDependencies、optionalDependencies、bundledDependencies。字段的差别不是"放哪个位置"的格式问题,而是"这段关系由谁负责"的契约问题。本节逐一勘验五种字段的精确语义、典型用例与高频误用,并给出 peer 依赖警告的处置决策树。写库、写插件、写组件库的人,这一节是必修课。

一次写错字段的发布事故

先看一次真实的翻车。某团队发布了一个组件库,为了"省事",把 React 写进了 dependencies。使用者安装后,应用里出现了两份 React——应用自己的和组件库拖进来的。症状随即出现:钩子调用报错(两份 React 各自维护一套内部状态)、包体积无端膨胀。回滚、改字段、重新发布,一天没了。

事故的机理一句话:组件库需要的不是"拥有一份 React",而是"借用宿主的那份 React"——这两种关系在清单里有不同的字段表达。用错字段,就是把"借用"写成了"自带"。下面把五种关系逐一讲清,这类事故就能在发布前被看见。

五种字段逐一勘验

dependencies:运行时必需,我负责。 包在别人环境里运行时必须存在的依赖。装你的包,这些依赖自动安装。判定口诀:你的代码被 import 时真正加载到的包,全在这里。

devDependencies:只在开发期需要,使用者不用管。 测试框架、构建工具、类型检查器——你的开发流程需要它们,但发布产物不含你的测试代码。使用者装你的包时,这类依赖默认跳过。高频误用:把构建期工具错放进 dependencies,让所有使用者白装一套构建链。

peerDependencies:宿主必须自备,我只声明要求。 组件库与 React 的关系、插件与框架的关系——我不安装它,但要求环境里已存在且版本落在我的兼容范围。这是"借用关系"的正式表达,前面事故的正确写法就是把 React 声明在这里。2.1 节讲过它在解析层的特殊性:全部 peer 约束必须在一份版本上协商一致,冲突在安装时报错。

optionalDependencies:装得上就用,装不上不碍事。 平台相关的可选加速包(比如某个只在特定操作系统可用的原生加速模块)、或提供额外功能但缺了也能跑的包。安装失败不阻断整个安装。典型用例是"环境探测型"包:主包运行时检查可选包是否存在,在则走快路径。

bundledDependencies:随包发行,不走仓库。 声明在此的依赖会在发布时被打进包内。用得少,适合"依赖必须与本包同版本发行"的特殊场景。知道它的存在即可,临时不必深究。

图 5-3 五种依赖关系:谁安装、谁使用、谁负责

图 5-3 五种依赖关系:谁安装、谁使用、谁负责

peer 依赖警告的处置决策

工具链升级后,peer 依赖警告几乎人人的项目里都有几条。看到警告按这棵决策树走:

警告内容:包 X 要求宿主提供 react 的某范围 ├─ 应用清单里已装 react 且版本落在范围内? │ └─ 是 → 警告可安全忽略(提示性)或更新声明范围更整洁 ├─ 已装但版本不在范围内? │ └─ → 真问题:升级应用侧 react 或联系包 X 要求放宽范围 └─ 应用根本没装 react? └─ → 要么你是库作者忘了写文档,要么这个包装错了地方

库作者侧还有一条配套纪律:peer 声明的范围要宽进严出——声明你真正兼容的最宽范围,而不是你测试过的最窄范围;范围写得过窄会把大量能用却版本略新的宿主拒之门外,徒增使用者的降级成本。

Monorepo 里字段误用被放大

单包仓库里字段写错的代价是偶发问题,工作区仓库里会被放大成发布事故。两个高发场景:其一,子包互相把对方写进 devDependencies。开发时软链接让一切正常(5.1 节的链接不区分字段),发布后使用方安装却缺依赖——因为 dev 依赖不会被使用者安装。其二,工具链配置只对顶层生效。测试框架装在顶层 devDependencies 里没问题,但某个子包单独发布后,使用者若直接依赖该子包,其构建配置不会随包传播——发布内容的完整性要在子包各自的清单里自足。

两案的共同预防是发布预演:模拟发布输出里会列出将要发布的文件与依赖解析结果,字段写错在这里几乎都会现形。把它设为发布流程的固定一步,成本一分钟,止损一整天。

场景速查表:什么依赖放什么字段

场景 正确字段 一句话理由
库运行时加载的包 dependencies 使用者安装时必须自动带上
测试与构建工具 devDependencies 使用者不需要你的测试框架
组件库对框架的依赖 peerDependencies 必须共用宿主的那一份
平台专属加速模块 optionalDependencies 装不上不碍事,运行时探测降级
应用依赖工作区内部包 dependencies 发布之后这条关系依然成立

表里最常被拿错的是最后一行的近亲:工作区里以为"反正是本地链接,字段无所谓"——5.1 节的事故机理已经证明,发布之后字段就是合同。顺手给一个自检技巧:对着自己的清单逐行问"使用者装到这个包时,这一行该不该跟着装进他的环境"——该则 dependencies,不该则 dev,要求宿主自备则 peer。三问归位,字段不会错。

本节要点回顾

  • 五种字段三种契约:我自带(dependencies)、你自备(peerDependencies)、尽力而为(optionalDependencies),外加开发期专用与随包发行两个特殊位;
  • 开头事故的答案:组件库对 React 的关系是"借用"不是"自带",字段写错就拖出第二份实例;
  • dev 与 dependencies 的分界线:你的代码被使用者加载时是否真的会 import 它——会则 dependencies,不会则 dev;
  • peer 范围宽进严出:声明真正兼容的最宽范围,别把测试范围当兼容范围;
  • Monorepo 放大效应:dev 误放会在发布后现形,发布预演是固定的低成本保险。

第五章收官。第六章转向攻防与效能:包管理器的安装期能力(脚本、缓存、哈希)如何在攻击者眼里变成攻击面,以及从审计到私有源的完整防线。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U