运行npm run XXX 的时候到底发生了什么?

相信这个问题在前端面试的时候经常遇到,虽然我没有面试,但是在刷面试题的时候,突然遇到问个问题,一开始还没咋留意,想想无非就是找到package.json文件里的scripts找到对应的命令去执行,就比如我们在运行npm run serve的时候,就是在执行vue-cli-service-serve这条命令。

1
2
3
4
5
6
7
8
{
'name': 'h5',
'version': '1.0.0',
'private': true,
scripts: {
'serve': 'vue-cli-service-serve'
}
}

这点常识学习过前端的人应该都知道,我觉得这就是所谓答案了吧,但是我发现我还是太天真了,真的所有东西都太片面了,想要真正了解一个东西的作用,不能光从他带来的结果分析,要从整件事情的过程全面分析,完完全全的了解他的机制以及目的才能真正了解他的作用是什么。

通过查阅大量资料,我也对这个过程有所了解了,我们就来聊一聊npm run XXX的过程到底发生了什么,也算是我对知识的巩固和学习的记录吧,但是这些都是我个人的理解,有什么不对的地方,可以提出来,大家一起学习一下。

学过node的同学应该知道,node的依赖管理器是npm,虽然不是唯一的,但是其他的依赖管理器也都是跟npm差不多的原理,就是针对npm的每个缺点做出解决的办法。他们都只是对package.json依赖声明文件进行解析,过程就如上面所说一样。既然就是通过解析package.json文件来执行相应的命令,那为什么不直接执行命令而是要去创建一个声明文件,然后解析执行呢?

其实就是一个查找顺序的程序,当我们执行npm run XXX的时候,npm首先会在node_modules/.bin文件中查找可执行文件,当没有找到时就会从全局的node_modules/.bin文件中去寻找,如果都没有找到,那就会在环境变量path的变量去寻找同名的可执行文件。

那这些可执行文件到底是怎么来的呢?

image-20220408131247493

很多人可能只知道npm install xxx的时候会将模块导入node_moduels文件夹当中,可是很多人忽略了.bin文件下的变化,每当文墨执行npm install的时候,npm就会将该文件软连接到./node_modules/.bin目录下,并且将目录加入到$PATH,,这样的好处在于可以直接运行命令运行依赖程序和开发依赖程序,免去全局安装的麻烦。如果执行的是npm install -g xxx就会将bin文件加入到全局。

npm install的时候建立的软连接将我们映射关系配置好了,当我们执行npm run xxx的时候,就会找到相应的可执行文件来执行相应的js文件。

打开.bin文件我们会发现,每一个可文件都是三个不同的文件,这是因为在不同的系统中,他们的可执行文件是不同的,比如在windows中,科执行文件是通过环境变量和组策略决定的,环境变量决定了可执行文件的后缀,在windows系统中执行npm run xxx实际上是调用了xxx.cmd文件。三个不同的文件作用于不同的系统。

1
2
3
4
5
6
7
8
# nuix 系统默认的可执行文件,必须输入完整文件名
vue-cli-service

# windows cmd 中默认可执行文件,当我们不添加后缀名时,自动根据pathext查找文件
vue-cli-service.cmd

# windows PowerSheel 中可执行文件,可跨平台
vue-cli-service.ps1

当然,用的最多还是windows的cmd脚本,他的兼容性也是最好的,其他脚本在运行的时候命令也会有所不同,在使用其他脚本执行的时候,如果出现问题,不妨试一试cmd,他会给你带来惊喜。

总结一下

1.运行npm run xxx的时候,首先会在当前目录的node_modules/.bin中查找要执行的程序,如果找到了,就直接运行

2.如果当前目录没有找到,就会自爱全局目录寻找。

3.如果都没有找到,就会在path环境变量中寻找。