npm install是干嘛的
npm install命令用来安装模块到node_modules目录。
安装之前,npm install会先检查node_modules目录之中是否已经存在指定模块。如果存在,就不再重新安装了,即使远程仓库已经有了一个新版本,也不会安装。
如果希望一个模块不管是否安装过,npm 都要强制重新安装,可以使用-f或--force参数。
1 | npm install <packageName> --force |
1 | npm install --verbose |
运行命令,会把安装过程的log输出。

registry
npm 模块仓库提供了一个查询服务,叫做 registry,npmjs.org 的查询服务网址是https://registry.npmjs.org/
后面可以加上npm包名,比如:https://registry.npmjs.org/npm-study4,打开地址是一个JSON 对象,里面是该模块所有版本的信息。dist.tarball属性是该版本压缩包的网址,打开这个网址就可以下载npm压缩包,在本地解压,就可以获得源码,npm install和npm update命令,都是通过这种方式安装模块。

npm update
1 | npm update <packageName> |
它会先到远程仓库查询最新版本,然后查询本地版本。如果本地版本不存在,或者远程版本较新,就会安装。
缓存
1 | 获取目录的具体位置 |
要注意在 npm@5 之后
- 缓存数据放在
.npm/_cacache文件夹中 - 清除命令清除的是
.npm/_cacache目录下文件
那么看一下.npm/_cacache目录下

在content-v2 里面基本都是一些二进制文件,把二进制文件的扩展名改为 .tgz 再解压之后,会发现就是在我们熟知的npm包。

而index-v5 里面是一些描述性的文件,也是 content-v2 里文件的索引,有点像HTTP的响应头,而且还有缓存相关的值

所以npm install之后发生了什么
先了解一下shell的解释行(Shebang)是什么
Shebang(也称为Hashbang)是一个由井号和叹号构成的字符串行(#!),其出现在文本文件的第一行的前两个字符。
如下列出了一些典型的shebang解释器指令:
1 | #!/bin/sh—使用sh,即Bourne shell或其它兼容shell执行脚本 |
通常出现在linux的shell脚本第一行,作为解释行,告诉解释器shell的执行方式。
在npm入口文件后面添加--inspect-brk就可以断点调试
1 |
入口文件在:

前置条件:npm版本6.4.1,不存在package-lock.json,以及没有缓存文件存在的情况。
1.入口文件进入
2.加载install.js


1 | function Installer (where, dryrun, args, opts) { |
1 | Installer.prototype.run = function (_cb) { |
3.经历install的生命周期
在各种生命周期中做了的一些事情:
读根目录下package.json文件,确定依赖树

获取元信息

获取包信息,就是要安装的包的数据

内容:

下载的.tgz后缀的压缩包,比如http://registry.npmjs.org/npm-study1/-/npm-study1-2.0.0.tgz,保存到.npm/_cacache文件夹,解压到node_modules目录下,创建package-lock.json文件。
补充:
当运行npm install的时候,会检查node_modules目录下,并不是node_modules目录下有依赖包,就不安装了(情况比较多)。
如果node_modules目录下没有这个文件,缓存里有的话,据我对打印出log的观察,应该是从缓存里解压到node_modules目录下。
那么哪些操作会更新package.json或更新package-lock.json,同时更新node_modules下的依赖包?
当node_modules下不存在某依赖包:
npm init初始化后,npm install xxx(高版本的npm)会自动更新package.json文件,并且在最后创建package-lock.json文件,同时更新node_modules下的依赖包。
当node_modules下存在某依赖包:
1)^版本号情况下, package.json中某个依赖包的小版本要大于package-lock.json中的同个依赖包小版本,
npm install的时候,会修改package-lock.json文件,同时更新node_modules下的依赖包(安装某依赖包为当前大版本下的最新版本)。 小于的话,更新node_modules下的某依赖包,版本号与package-lock.json版本号一致。
2)版本号具体到某个版本的话,只要和node_modules下的依赖包版本不同,就会安装。
2)npm update packageName,更新package.json文件,同时更新node_modules下的某依赖包,版本号为当前依赖包大版本号下最新的版本(比如2.1.0就升到2.9.0,不会超过3.0.0)。
4)或者npm install xxx@x.x.x,更新package.json文件,更新package-lock.json文件,更新node_modules
5)npm uninstall packageName <args>,更新package.json文件,更新package-lock.json文件,更新node_modules