ng new app 生成的 Angular 利用,自带 11 个依赖:
应用 Schematics 装置了 library 之后的客户 Storefront:
本地新建一个空的文件夹,在外面执行命令行:npm i @spartacus/storefront
外面只有一个 node_modules 文件夹,外面蕴含了很多 js 文件和 TypeScript 的 .d.ts 文件:
这个 @Spartacus/storefront 的 package.json 里,仍旧只有一个 tslib 的 dependencies:
然而 peerDependencies
里,蕴含了不少在 Spartacus 我的项目源代码 package.json 里定义的 dependencies
:
"peerDependencies": {
"@angular/common": "^12.0.5",
"@angular/core": "^12.0.5",
"@angular/forms": "^12.0.5",
"@angular/platform-browser": "^12.0.5",
"@angular/router": "^12.0.5",
"@angular/service-worker": "^12.0.5",
"@ng-bootstrap/ng-bootstrap": "^10.0.0",
"@ng-select/ng-select": "^7.0.1",
"@ngrx/effects": "^12.1.0",
"@ngrx/router-store": "^12.1.0",
"@ngrx/store": "^12.1.0",
"@spartacus/core": "4.3.1",
"ngx-infinite-scroll": "^8.0.0",
"rxjs": "^6.6.0"
},
npm 很好地解决了子依赖关系:如果我的包依赖于 request 版本 2 和其余库,但其余库依赖于 request 版本 1,则生成的依赖关系图如下所示:
这通常很棒:当初 some-other-library 领有本人的申请 v1 正本,它能够应用它,同时不会烦扰我的包的 v2 正本。
然而,有一个用例会失败:插件 (plugin)。插件包旨在与另一个 host 包一起应用,即便它并不总是间接应用 host 包。Node.js 包生态系统中曾经有很多这种模式的例子:
- Grunt plugins
- Chai plugins
- LevelUP plugins
- Express middleware
- Winston transports
从实质上讲,插件旨在与主机包一起应用。但更重要的是,它们旨在与特定版本的主机包一起应用。例如,我的 chai-as-promised 插件的 1.x 和 2.x 版本实用于 chai 0.5 版,而 3.x 版实用于 chai 1.x。另一个例子是 grunt. 0.3.1 版的 grunt-contrib-stylus 能够与 grunt 0.4.0rc4 一起应用,但因为删除了 API,在与 grunt 0.4.0rc5 一起应用时会中断。
假如 plugin 显式申明了 host package 的版本号,即便对于的确具备这种间接依赖关系的插件,可能是因为主机包提供了实用程序 API,在插件的 package.json 中指定依赖项也会导致依赖关系树蕴含主机包的多个正本。例如,假如 winston-mail 0.2.3 在其 dependencies 中指定了 winston: 0.5.x,因为这是对其进行测试的最新版本。
作为应用程序开发人员,应用了 winston 的最新版本 0.6, 将它们放在 package.json 中:
一旦运行 npm install
后,产生 winston 的两份不同的版本:
这种问题的解决方案就是 peerDependencies
.
peerDependencies 应用起来非常简单。在编写 plugin 时,请确定 peerDependencies 的 host package 的版本,并将其增加到 package.json 中:
{
"name": "chai-as-promised",
"peerDependencies": {"chai": "1.x"}
}
当初,当装置 chai-as-promised 时,chai 包将随之被装置。
如果稍后尝试装置另一个仅实用于 0.x 版本的 Chai 的 Chai 插件,将收到谬误音讯。