运用NPM装置的时刻会经常出现包争执(比方多个主模块的子模块版本不一致等),致使在开辟历程中会碰到种种或大或小的题目。一切在这会引见以下内容:
- NPM 重要装置体式格局
- NPM 包信息查询
- NPM 装置机制(重要)
装置&查询敕令
NPM 种种装置体式格局
npm install packageName[@next | @versionNumber]
- 在 node_modules 中没有指定模块时装置,(不搜检~/.npm目次)
npm install packageName --f | -- force
- 一个模块不论是不是装置过,npm都要 强迫重新装置
npm update packageName
- 假如长途版本较新、或许当地版本不存在时装置
NPM 查询效劳
- NPM经由过程registry的查询效劳,从而晓得每一个模块的最新版本。
- 能够经由过程
npm view packageName [version]
查询对映模块的信息
NPM 装置机制
输入 npm install 敕令并敲下回车后,会阅历以下几个阶段(以 npm 5.5.1 为例):
1. 实行工程自身 preinstall
当前 npm 工程假如定义了 preinstall 钩子此时会被实行。
2. 肯定首层依靠模块
起首须要做的是肯定工程中的首层依靠,也就是 dependencies
和 devDependencies
属性中直接指定的模块(假定此时没有增加 npm install 参数)。
工程自身是整棵依靠树的根节点,每一个首层依靠模块都是根节点下面的一棵子树,npm 会开启多历程从每一个首层依靠模块最先逐渐寻觅更深层级的节点。
假如查询node_modules目次当中已存在指定模块,那末不再重新装置
3. 猎取模块
猎取模块是一个递归的历程,分为以下几步:
猎取模块信息
- 在下载一个模块之前,起首要肯定其版本,这是由于 package.json 中往往是 semantic version(semver,语义化版本)
- 此时假如版本形貌文件(npm-shrinkwrap.json 或 package-lock.json)中有该模块信息直接拿即可
- 假如没有则从堆栈猎取(向registry查询)。如 packaeg.json 中某个包的版本是 ^1.1.0,npm 就会去堆栈中猎取相符 1.x.x 情势的最新版本。
猎取模块实体。
- 上一步会猎取到模块的压缩包地点(resolved 字段),npm 会用此地点搜检当地缓存,缓存中有就直接拿,假如没有则从堆栈下载。
查找该模块依靠
- 假如有依靠则回到第1步,假如没有则住手。
4. 模块扁平化(dedupe)
一步猎取到的是一棵完全的依靠树,个中能够包括大批反复模块。比方 A 模块依靠于 loadsh,B 模块一样依靠于 lodash。在 npm3 之前会严厉根据依靠树的构造举行装置,因此会形成模块冗余。
从 npm3 版本
最先默许加入了一个 dedupe 的历程。它会遍历一切节点,逐一将模块放在根节点下面,也就是 node-modules 的第一层。当发现有反复模块时,则将其抛弃。
这里须要对反复模块举行一个定义,它指的是模块名雷同且 semver 兼容。每一个 semver 都对应一段版本许可局限,假如两个模块的版本许可局限存在交集,那末就能够获得一个兼容版本,而没必要版本号完全一致,这能够使更多冗余模块在 dedupe 历程中被去掉。
比方
- node-modules 下 foo 模块依靠 lodash@^1.0.0,bar 模块依靠 lodash@^1.1.0,则 ^1.1.0 为兼容版本。
- 而当 foo 依靠 lodash@^2.0.0,bar 依靠 lodash@^1.1.0,则根据 semver 的划定规矩,两者不存在兼容版本。会将一个版本放在 node_modules 中,另一个仍保存在依靠树里。
举个例子,假定一个依靠树原本是如许:
node_modules
— foo
—- lodash@version1
— bar
—- lodash@version2
假定 version1 和 version2 是兼容版本,则经由 dedupe 会成为下面的情势:
node_modules
— foo
— bar
— lodash(保存的版本为兼容版本)
假定 version1 和 version2 为非兼容版本,则背面的版本保存在依靠树中:
node_modules
— foo
— lodash@version1
— bar
—- lodash@version2
5. 装置模块
这一步将会更新工程中的 node_modules,并实行模块中的性命周期函数(根据 preinstall、install、postinstall 的递次)。
6. 实行工程自身性命周期
当前 npm 工程假如定义了钩子此时会被实行(根据 install、postinstall、prepublish、prepare 的递次)。
末了一步是天生或更新版本形貌文件,npm install 历程完成。
End
文章分享同步于:
https://github.com/zhongmeizh…
参考