>[success] # npm -- install 安装流程 ~~~ 1.npm install 执行之后,首先,检查并获取 npm 配置,这里的优先级为:项目级的 .npmrc 文件 > 用户级的 .npmrc 文件> 全局级的 .npmrc 文件 > npm 内置的 .npmrc 文件。然后检查项目中是否有 package-lock.json 文件。 ~~~ * 无 lock 文件: * 从 npm 远程仓库获取包信息 * 根据 package.json 构建依赖树,构建过程: * 构建依赖树时,不管其是直接依赖还是子依赖的依赖,优先将其放置在 node\_modules 根目录。 * 当遇到相同模块时,判断已放置在依赖树的模块版本是否符合新模块的版本范围,如果符合则跳过,不符合则在当前模块的 node\_modules 下放置该模块。 * 注意这一步只是确定逻辑上的依赖树,并非真正的安装,后面会根据这个依赖结构去下载或拿到缓存中的依赖包 * 在缓存中依次查找依赖树中的每个包 * 不存在缓存: * 从 npm 远程仓库下载包 * 校验包的完整性 * 校验不通过: 重新下载 * 校验通过: * 将下载的包复制到 npm 缓存目录 * 将下载的包按照依赖结构解压到 node\_modules * 存在缓存: * 将缓存按照依赖结构解压到 node\_modules * 将包解压到 node\_modules * 生成 lock 文件 * 如图 ![](https://img.kancloud.cn/5a/56/5a56994219db210597aef684b2bcf363_826x649.png) >[info] ## 什么是.npmrc ~~~ 1.'.npmrc文件',就是npm的配置文件。修改配置文件 -- 'npm config edit',在弹出的界面 上,修改.npmrc文件后,保存即可 2.'.npmrc 文件' 位置 2.1.每个项目的配置文件 -- (/path/to/my/project/.npmrc) 项目里面如果和package.json同级存放了这个.npmrc 2.2.每个用户的配置文件 -- (~/.npmrc) 通过 'npm config ls -l' 指令找到'userconfig'字段看到具体位置,或者'npm config get userconfig' 2.3.全局配置文件 -- ($PREFIX/etc/npmrc) 通过 'npm config ls -l' 指令找到'globalconfig'字段看到具体位置,或者'npm config get globalconfig' 2.4.npm 内置配置文件 -- (/path/to/npm/npmrc) 就是全局'node_modules'下的npm里面 3.'.npmrc配置文件'中字段解释'https://www.npmjs.cn/misc/config/' 4.指令配置'https://docs.npmjs.com/cli/v7/commands/npm-config' ~~~ >[info] ## 缓存 ~~~ 1.在执行 'npm install' 或 'npm update'命令下载依赖后,除了将依赖包安装在 'node_modules' 目录下外,还会在本地的缓存目录缓存一份。查看缓存地址的指令: 'npm config get cache' 2.'cache'文件打开 可以看到三个文件 'content-v2' 、'index-v5'、 'tmp' 2.1.'content-v2'目录用于存储'tar'包的缓存,里面基本都是一些二进制文件,想具体看懂 文件到底是什么,将这些二进制文件的扩展名改为 '.tgz',然后进行解压,得到的结果其实 就是我们的 npm 包资源 2.2.'index-v5'目录用于存储'tar'包的'hash',这些内容就是 content-v2 里文件的索引 3.找到缓存文件。这里我在项目中安装一个'sass-loader',得到了'package-lock.json' 文件找到'sass-loader对应resolved字段',这里我是通过linux指令的文件查找, (win没研究明白),通过在'index-v5'文件找到存储'tar'包的'hash' ' grep "https://registry.npmjs.org/sass-loader/-/sass-loader-12.1.0.tgz" -r index-v5' 在找到对应文件内容中搜索字段'_shasum',将这段vaule 在'content-v2 ' 文件搜索 举个例子上面的 _shasum 属性 6926d1b194fbc737b8eed513756de2fcda7ea408 即为 tar 包的 hash, hash的前几位 6926 即为缓存的前两层目录,文件目录如下 'content-v2/69/26/d1b194fbc737b8eed513756de2fcda7ea408' 既可以找到缓存的压缩包文件 ~~~ * cache 结构目录 ![](https://img.kancloud.cn/43/0a/430ad9d8e597e8911e95d21ce764f462_195x121.png) * resolved字段 ![](https://img.kancloud.cn/fd/e8/fde8a67786ac32626ffaf721e823e587_804x306.png) * index-v5 文件 ![](https://img.kancloud.cn/62/0f/620f9ab0e998b1ff3d5351d2acb5432e_1861x249.png) >[danger] ##### 通过npm info 找shasum ~~~ 1.在对应项目下输入'npm info 查看的包名' ~~~ ![](https://img.kancloud.cn/1f/0c/1f0cfb6cc5a0f57b031b3347ab560413_1038x609.png) >[danger] ##### 整体流程 当 npm install 执行时,通过[pacote](https://www.npmjs.com/package/pacote)把相应的包解压在对应的 node\_modules 下面。npm 在下载依赖时,先下载到缓存当中,再解压到项目 node\_modules 下。pacote 依赖[npm-registry-fetch](https://github.com/npm/npm-registry-fetch#npm-registry-fetch)来下载包,npm-registry-fetch 可以通过设置 cache 属性,在给定的路径下根据[IETF RFC 7234](https://datatracker.ietf.org/doc/rfc7234/)生成缓存数据。 接着,在每次安装资源时,根据 package-lock.json 中存储的 integrity、version、name 信息生成一个唯一的 key,这个 key 能够对应到 index-v5 目录下的缓存记录。如果发现有缓存资源,就会找到 tar 包的 hash,根据 hash 再去找缓存的 tar 包,并再次通过[pacote](https://www.npmjs.com/package/pacote)把对应的二进制文件解压到相应的项目 node\_modules 下面,省去了网络下载资源的开销。 >[danger] ##### 缓存参考的文章 [npm缓存现在是怎么做的?细节一定必读](https://www.zhihu.com/question/305539244) >[info] ## 参考文章 [npm基本用法及原理(10000+) - 漫漫字节|漫漫编程 (mmbyte.com)](https://www.mmbyte.com/article/185966.html) [前端工程化 - 剖析npm的包管理机制 (juejin.cn)](https://juejin.cn/post/6844904022080667661#heading-56) [npm及.npmrc文件](https://blog.csdn.net/yexudengzhidao/article/details/109702948) [链接](https://kaiwu.lagou.com/course/courseInfo.htm?courseId=584#/detail/pc?id=5906)