主题
npm run命令执行过程
1. npm依赖的种类有那些?
在开发中,项目发package.json
文件中,常见的或常用的就是开发依赖devDependencies
和生产依赖dependencies
,分别通过--save-dev
和 --save
来进行安装,除了这两种依赖之外,其他还有一些不常用的依赖,例如 同等依赖,打包依赖,可选依赖,等
devDependencies
:开发依赖 仅在开发阶段会使用的依赖,打包时候不会被打包,例如一些loader
;dependencies
:生产依赖 仅在生产环境下需要的依赖,可通过npm install --production
来下载所有的生产依赖,例如nuxt上线后,仅仅只需要生产依赖。peerDependencies
:同等依赖 可有可无,主要作用是用来在安装时候进行提示用的。例如:bootstrap
依赖于jquery
,那么,可以在peerDependencies
内放入jquery
,用户在安装bootstrap
的时候,就知道需要安装jquery
了;optionalDependencies
:可选依赖 可有可无,也是做提示用的。bundledDependencies
:捆绑依赖(npm压缩) 主要作用是在npm pack
压缩项目时候,指定需要将那些node_modules中的依赖一起压缩,若没有指定任何依赖,则打包后的压缩包内不包含node_modules,bundledDependencies:['dayjs']
,其值为数组
使用npm pack
打包tgz
时会将捆绑依赖一同打包
npm pack
打的压缩包,可以直接解压使用
注意:npm i
在安装依赖的时候只会下载开发依赖和生产依赖,其他的三个依赖不会自动下载
2. .bin
目录是干什么的?
在安装好依赖后,node_modules
目录下会多出一个.bin
目录,这个目录不属于任何的依赖包,也不是依赖项,里面存放的是一些可执行脚本文件,.bin
目录的意义意味着你安装的一些模块可以在命令行中执行。
但是,要区分是全局安装还是项目安装,
- 若是全局安装,会在全局的
node_modules
目录下的.bin
中新增脚本, - 若是项目安装,是在项目的
node_modules
下的.bin
中新增脚本文件
全局安装的可以直接在命令行执行,项目安装的必须得npm run xxx
,且需要配置scripts
脚本
为什么呢?
对于全局依赖,由于npm
已经在环境变量里面了,所以npm下面的目录可以全局执行(另一篇文章有详细介绍) 对于项目依赖,下面有介绍
3. npm run xxx
时候做了什么?
我们知道,安装到项目的命令依赖不能直接在命令行执行,得通过npm run xxx
才能执行,且必须在scripts
内先配置相应的脚本启动命令,这是为何呢?
上面说过,项目的node_modules
的.bin
目录下存放着一堆脚本文件,我们在执行npm run xxx
命令的时候,其实就是执行项目的node_modules
目录下的.bin
中某个xxx
脚本,那只需要搞清楚,npm run
的时候是咋能找到.bin
中的脚本这个问题,就知道npm run xxx
的原理了。
3.1 npm run env
首先,我们要知道npm run env
这个命令的作用,可以将全局现有的环境变量打印出来,且这个命令不属于某个项目内配置的scripts
脚本。
可以看到,运行了npm run xxx
命令时,做的事情就是设置环境变量,并且很重要的一点,就是将当前所在目录(global-module)的node_modules
下的.bin
目录也加入到系统path
环境变量下面,这就是为何在npm run xxx
命令的时候,.bin
目录下面的xxx命令都可以能被找到并执行的原因。
但是,这个这仅仅在npm run
时候才生效,当执行完npm run
命令后,就会自动从环境变量中删除刚刚添加进去的node_modules
下面的.bin
这个环境变量,可以直接在命令行运行path
来验证,path
能打印出当前计算机内的paht
内的环境变量;
可以看到,系统内是没有node_modules/.bin
这个环境变量了,再执行.bin
下面的xxx
脚本,就会报xxx不是内部或外部命令,也不是可运行的程序或批处理文件。
npm run
去执行一个脚本,若这个脚本对应的包在项目内安装了,就如上面所说,会根据零时环境变量,先找项目的node_modules
下的.bin
目录内的脚本,若是项目内没有安装,但是全局安装了,那么就会在环境变量中找到全局的node_modules
下的`对应包来执行。
3.2 pre
与 post
命令
npm
的scripts脚本中, 除了自定义脚本名称外, 还提供了两个前置(pre
)与后置(post
)钩子命令, 把这俩命令拼接到自定义命令前面, 就可以实现前置或后置钩子指令了,例如:
json
"scripts":{
"predev":"node ./predev.js",
"dev": "vite",
"postdev": "node ./postdev.js",
}
这样运行 npm run dev
指令的时候,终端会自动先运行 npm run predev
,再运行 npm run dev
,最后运行 npm run postdev
,通过这种方式,我们就可以在自定义脚本运行前,执行一些前置或者后置操作, 比如先对包管理器进行判断, 然后强制开发者使用哪种包管理器。
4. npx xxx
npx
命令是npm v5.2
之后引入的新命令,npx
可以帮我们直接执行node_modules/.bin
文件夹下的文件
npx
运行脚本核心原理和 npm
类似,但是npx
有一点不一样,就是在执行npx
脚本时候,若包不存在,就会先下载,然后通npm
一样运行下载的包,等脚本执行完毕又自动删除刚刚下载的包。
- 执行脚本
shell
npx webpack
省去了配置scripts
脚本
npx
避免了安装全局模块 全局安装的模块会带来很多问题,例如:多个用户全局安装的模块版本不同
shell
npx create-react-app react-project
我们可以直接使用 npx
来执行模块,它会先进行安装,安装执行后会将下载过的模块删除~,这样可以一直使用最新版本啦~
5. scripts
配置
在package.json
中可以定义自己的脚本通过npm run
来执行
json
"scripts": {
"hello": "echo hello",
"build": "webpack"
}
我们可以使用 npm run hello
执行脚本,也可以使用 npm run build
执行node_modules/.bin
目录下的webpack
文件
npm run
命令执行时,会把./node_modules/.bin/
目录添加到执行环境的PATH
变量中,因此如果某个命令行包未全局安装,而只安装在了当前项目的node_modules
中,通过npm run
一样可以调用该命令。- 执行
npm
脚本时要传入参数,需要在命令后加--
标明, 如npm run hello -- --port 3000
可以将--port
参数传给hello
命令` npm
提供了pre
和post
两种钩子机制,可以定义某个脚本前后的执行脚本,没有定义默认会忽略
json
"scripts": {
"prehello":"echo prehello",
"hello": "echo hello",
"posthello":"echo posthello"
}
可以通过打印全局env
和 在项目下执行npm run env
来对比PATH
属性,不难发现在执行npm run
的时候确实会将 ./node_modules/.bin/
目录添加到PATH
中
6. 协议
这张图就说明了为什么MIT许可
是最大的了