Tip:本文主要讨论npm@6.13.4、yarn@1.21.1行为的相关问题。
下文中我们会以package.json
做简单示例
{
"name": "package-a",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {},
"author": "gaojian.superior",
"license": "ISC",
"dependencies": {
"lodash": "^4.17.15"
},
"devDependencies": {
"react": "^16.13.0"
},
"peerDependencies": {
"react": ">16.8.0"
}
}
首先我们准备一下相关的测试环境:
# 创建测试文件夹
mkdir npm-test
cd npm-test
# 创建 package-a 包
mkdir package-a
cd package-a
npm init
# 创建 package-b 包
mkdir package-b
cd package-b
npm init
# 创建 package-c 包
mkdir package-c
cd package-c
npm init
npm 和 yarn 行为
那么让我们看一下在不同配置的情况下npm和yarn的行为。
我们主要关注两个点:node_modules的组成、yarn.lock & package-lock.json
npm 行为
接下来我们将 package-a 中package.json改为文章开头的配置
npm 关于 peerDependencies 的提示
我们在 package-b 文件夹下开始我们的测试。
# 在 package-b 执行
npm install ../package-a
我们先看一个执行命令的相关提示:
这里 npm 会有 warning 提示:package-a 包需要一个 peerDependencies 依赖包 query-string,但是当前并没有安装 query-string 包,你应该自己安装 query-string 包的依赖。
这里我们要注意一点:peerDependencies 在 npm 安装时起到的作用是提使用方应该安装相关的依赖,以保证包可以正确执行。
那么如果我们不想 npm 提示这样的问题该如何做呢?
非常简单,我们先安装 query-string 包就不会出现 warning 提示了。
npm 引用包含 peerDependencies 依赖的 npm 包
接下来我们在 package-b 不先安装 query-string 包,仅仅安装 package-a 时,node_modules 的结构:
我们可以看到 package-b 的 node_modules 只安装了 package-a ,并没有安装 package-a 的所前置依赖的 peerDependencies 相关依赖。
npm 引用包含 dependencies 依赖的 npm 包
接上一个我们仅在 package-b 中安装了 package-a 包,其中 package-a 包中 dependencies 里依赖了 lodash ,所以在安装 package-a 时,npm 也会安装 package-a 中 dependencies 所依赖的全部 npm 包,而且没有安装 package-a 中 devDependencies 所依赖的 npm 包。
总结一下,当我们引入一个包时:
- 会同时引入这个包 dependencies 中的全部依赖
- 不会引入这个包 devDependencies 中的全部依赖
- 如果这个包包含了 peerDependencies,则会检查当前是否已引入相关依赖,如果没有则提示 warning
npm 引入两个包含相同 dependencies 依赖的 npm 包 - 版本号相同
如果我们引入两个包包含相同版本号的 dependencies 依赖时,npm 会是什么行为呢?
这时我们将 package-c 包的 package.json 和 package-a 包的 package.json 一致。
我们回到 package-b 分别引入 package-a 和 package-c,看一下 package-b 的 node_modules 结构。
我们惊奇的发现 lodash 竟然被安装了两次,并且分别安装在各自的 node_modules 中。
由此我们可以发现:
当我们引入多个包,且这些包的 dependencies 包含相同依赖的包时
- npm 会多次安装相同的依赖包,并且将其分别放置上游的node_modules中
npm 引入两个包含相同 dependencies 依赖的 npm 包 - 版本号不同
如果我们引入两个包包含相同的 dependencies 依赖,但是版本号不同时,npm 会是什么行为呢?
这时我们将 package-c 包的 package.json 的 lodash 版本号改为 ^3.0.0。
我们回到 package-b 分别引入 package-a 和 package-c,看一下 package-b 的 node_modules 结构。
我们可以发现,安装行为和上边相同版本号的行为一致,分别安装到各自的node_modules里,我们分别看一下各个包下的 lodash 版本是不一致的。
yarn 行为
我们先准备好和npm行为一致的测试环境
yarn 关于 peerDependencies 的提示
我们在 package-b 文件夹下开始我们的测试。
# 在 package-b 执行
yarn install ../package-a
我们先看一个执行命令的相关提示:
这里 yarn 也会有 warning 提示:package-a 包需要一个 peerDependencies 依赖包 query-string,但是当前并没有安装 query-string 包,你应该自己安装 query-string 包的依赖。
这里我们要注意一点:peerDependencies 在 yarn 安装时与 npm 安装时的都会有相关提示的
那么如果我们不想 yarn 提示这样的问题该如何做呢?
非常简单,我们先安装 query-string 包就不会出现 warning 提示了。
yarn 引用包含 peerDependencies 依赖的 npm 包
接下来我们在 package-b 不先安装 query-string 包,仅仅安装 package-a 时,node_modules 的结构:
我们可以看到 package-b 的 node_modules 装了 package-a 和 lodash ,并没有安装 package-a 的 peerDependencies 相关依赖。
yarn 引用包含 dependencies 依赖的 npm 包
接上一个我们仅在 package-b 中安装了 package-a 包,其中 package-a 包中 dependencies 里依赖了 lodash ,所以在安装 package-a 时,yarn 也会安装 package-a 中 dependencies 所依赖的全部 npm 包,而且没有安装 package-a 中 devDependencies 所依赖的 npm 包。
总结一下,当我们引入一个包时:
- 会同时引入这个包 dependencies 中的全部依赖
- 不会引入这个包 devDependencies 中的全部依赖
- 如果这个包包含了 peerDependencies,则会检查当前是否已引入相关依赖,如果没有则提示 warning
这里我们注意到 yarn 和 npm 安装的一个区别:
- yarn 引用一个包时,会将这个包的 dependencies 依赖放置和 包同级
- npm 引用一个包时,会将这个包的 dependencies 依赖放置在包的node_modules下
yarn 引入两个包含相同 dependencies 依赖的 npm 包 - 版本相同
如果我们引入两个包包含相同的 dependencies 依赖时,npm 会是什么行为呢?
这时我们将 package-c 包的 package.json 和 package-a 包的 package.json 一致。
我们回到 package-b 分别引入 package-a 和 package-c,看一下 package-b 的 node_modules 结构。
这里我们可以发现 yarn 的行为和 npm 的行为不同:
- yarn 引用两个包包含相同的 dependencies 依赖会放置在与包同级,仅安装一次
- npm 引用两个包包含相同的 dependencies 依赖会分别放置在对应包的node_modules下,安装了两次
yarn 引入两个包含相同 dependencies 依赖的 npm 包 - 版本不同
如果我们引入两个包包含相同的 dependencies 依赖,但是版本号不同时,yarn 会是什么行为呢?
这时我们将 package-c 包的 package.json 的 lodash 版本号改为 ^3.0.0。
我们回到 package-b 分别引入 package-a 和 package-c,看一下 package-b 的 node_modules 结构。
我们可以发现,yarn 的安装行为发生了改变,lodash因为被依赖了两个版本,所以yarn也安装了两个版本,一个版本安装在包同级(被引用最多次的版本),另一个版本安装在包的node_modules下。
最终关于 npm & yarn 的安装行为总结:
- 关于 peerDependencies 的提示
- yarn : 提示安装
- npm : 提示安装
- 引用包含 peerDependencies 依赖的 npm 包
- yarn : 提示安装,但不主动安装
- npm : 提示安装,但不主动安装
- 引用包含 dependencies 依赖的 npm 包
- yarn : 安装 dependencies 全部依赖,并与该包同级
- npm : 安装 dependencies 全部依赖,放置到该包的node_modules下
- 引用包含 devDependencies 依赖的 npm 包
- yarn : 不做任何操作
- npm : 不做任何操作
- 引入两个包含相同 dependencies 依赖的 npm 包 - 版本相同
- yarn : 安装一次,与两个包同级
- npm : 安装两次,分别放到两个包的node_modules下
- 引入两个包含相同 dependencies 依赖的 npm 包 - 版本不同
- yarn : 安装两次,引用最多的版本放置与两个包同级
- npm : 安装两次,分别放到两个包的node_modules下
最后欢迎提出相关建议修改~谢谢啦~