首先,在一个空目录下本地安装express
然后查看当前npm的目录结构,如下图所示
这个结构是什么?和express有什么关系呢?
现在,查看位于/node_modules
目录下的express
的 package.json
文件。其中的dependencies
依赖如下图所示。
简单的对比两个图,发现图一express@4.17.1
的子树对应dependencies
。
通过一一核对,发现 验证了 图一的目录结构对应express
的 dependencies
。
- 结论1: 通过 npm安装
express
包会将express
的所有依赖都一起安装
那么,安装下来的版本号一致吗?
在npm文档中,对版本进行了说明
对于一个项目或包而言,在package.json
的dependencies
中声明依赖版本有这样的规则
~(波浪线)代表当前项目接受补丁版本,也就是如果你的项目依赖为版本为1.0.1的某个npm包(假设包名叫express
),当express更新到1.0.3的时候,你运行npm install,会自动将express
升级为1.0.3。
^(尖号) 代表当前项目接受 次要版本 ,也就是如果你的项目依赖为版本为1.0.1的某个npm包(假设包名叫express
),当express更新到1.3.2的时候,你运行npm install,会自动将express
升级为1.3.2。
如果没有加上版本号前没有加上修饰符修饰符,则表示指定该版本进行安装。
我们比较两者的版本号,再次声明:图一为实际安装的express
包依赖结构,图二为express
的 dependencies
。
经过对比发现,版本并不完全相同。其中,proxy-addr
包的版本依赖的是"proxy-addr": "~2.0.5"
2.0.5版本,而实际安装的是proxy-addr@2.0.6
2.0.6版本。
- 结论2:npm 安装的包会根据
package.json
中的dependencies
依赖修饰符,自动升级依赖的版本。
现在express
的dependencies
依赖搞清楚了。那么express
依赖的依赖呢?
比如 express
的第一个依赖accepts
在accepts
的package.json
中发现,它自身依赖两个包。
而通过npm list
命令得到express的依赖树中,子树也是这两个依赖包
并且在/node_modules
中找到了依赖。
继续发现,accepts
的依赖mime-types
的依赖mime-db
也遵循这个规则。
- 结论3:npm会递归的安装一个包的依赖。
假如一个项目中的两个npm包都依赖express,那么这样会将express及整个依赖树安装两遍吗?
观察树可以发现,其中有一些多次的被依赖的包。
但是层级更深的依赖后缀有一个deduped
(重复数据删除)的标识。
这意味着npm在安装包的过程中会检查当前是否已经安装过相同的包,如果有,则不再次安装。
- 结论4: npm会记录安装过的包,安装过程为广度优先