npm install 的实现原理

npm install 的实现原理?

输入npm install 命令并敲下回车后,会经历如下几下阶段(以npm5.5.1为例):

执行工程自身preinstall

当前npm 工程如果定义了perennial钩子此时会被执行。

确定首层依赖模块

首先需要做的是确定工程中的首层依赖,也就是dependencies 和 devDependencies属性中直接指定的模板(假设此时没有添加npm install参数)

工程本身是整颗依赖树的根节点,每个首层依赖模块都是根节点下面的一棵子树,npm会开启多进程从每个首层依赖模块中逐步寻找更深层次的节点。

获取模块

获取模块是一个递归的过程, 分为以下几步:

1.获取模块信息。 在下载一个模块之前,首选要确定器版本 这就是因为package.json中往往是semantic version .此时如果版本描述文件(npm-shrinkwrap.json 或 package-lock.json)中有该模块信息直接拿即可,如果没有则从仓库获取。如pachage.json中某一个包的版本是^1.1.0,npm就会去仓库中获取符合1.x.x 形式的最新版本,

2.获取模块实体,上一步会获取到模块的压缩包地址(resolved 字段),npm会用此地址检查本地缓存,缓存中有就直接拿,如果没有则从仓库中下载。

3.查找该模块依赖,如果有依赖则回到第一步,如果没有则停止。

模块扁平化(dedupe)

上一步获取到的是一颗完整的依赖树,其中可能包含大量重复模块。比如A模块依赖于lodash,B模块同样依赖于lodash.在 npm3 以前会严格按照依赖树的结构进行安装,因此会造成模块冗余。

从 npm3 开始默认加入了一个 dedupe 的过程。它会遍历所有节点,逐个将模块放在根节点下面,也就是 node-modules 的第一层。当发现有重复模块时,则将其丢弃。比如 node-modules 下已经有了一个 [email protected],此时又发现某模块下有一个 [email protected],则直接将其从依赖树中丢弃。

这里需要对重复模块进行一个定义, 它指的是模块名相同的semver兼职,每一个semver都对应一段版本的允许范围,如果两个模块的版本允许范围存在交集,那么就可以得到兼容一个版本,而不必要版本号完全一致,这可以使更多冗余模块在 dedupe 过程中被去掉。

安装模块

这一步将会更新工程中的node_modules,并执行模块中的生命周期函数(按照 preinstall、install、postinstall 的顺序)。

执行工程自身生命周期

当前npm工程如果定义了钩子此时会被执行,(按照 preinstall、install、postinstall 的顺序)。

最后一步是生成或者 更新版本描述文件,npm install 过程完成。

你可能感兴趣的:(Node.js相关)