Node.js 12实战
上QQ阅读APP看书,第一时间看更新

2.1.2 NPM的工作原理

对于包管理,首先要理解什么是包(Package)。包用于描述一个文件或一个目录。一个包的配置通常由以下部分构成:

· 一个文件夹包含一个package.json配置文件。

· 包含的GZIP压缩文件(含有package.json文件的文件夹)。

· 解析GZIP的URL。

· 为注册表添加<name>@<version>的URL信息。

模块是将一个复杂的程序依据一定的规则(规范)封装成几个块(文件),并组合在一起。换句话说,模块是通过配置文件中的节点包含一个或多个包。通常是由包、配置文件以及相关模块构成完整的一个或多个业务功能单元。块的内部数据/实现是私有的,只是向外部暴露一些接口(方法)与外部其他模块通信。

NPM允许在package.json文件中使用scripts字段定义脚本命令,例如:

{
// ...
"scripts":{
     "build":"node index.js"
}
}

这块代码是package.json文件的片段,其中scripts字段是一个对象,scripts对象的每一个属性对应一段脚本。其中build命令对应的脚本是node index.js。在命令行下运行npm run命令,就可以执行这段脚本:

$ npm run build
#等同于执行
$ node index.js

这些定义在package.json里面的脚本就称为NPM脚本。通过使用NPM脚本可以将项目中相关的脚本集中在一处。不同项目的脚本命令只要功能相同,就可以有同样的对外接口。同时,利用NPM可以提供很多辅助功能。

查看当前项目的所有NPM脚本命令,可以使用不带任何参数的npm run命令:

$ npm run

NPM脚本的原理相对简单,每当执行npm run时,会自动新建一个Shell,在该Shell中执行指定的脚本命令。因此,只要是Shell(一般是Bash)可以运行的命令,就可以写在NPM脚本里面。需要注意的是,npm run新建的Shell会将当前目录的node_modules/.bin子目录加入PATH变量,命令执行结束后,再将PATH变量恢复。

也就是说,当前目录的node_modules/.bin子目录里面的所有脚本都可以直接用脚本名调用,而不必加上路径。例如,当前项目的依赖里面有Mocha,只需要直接写mocha test即可:

{
script: {
     "test":"mocha test"
}
}

而不需要写成:

{
script: {
     "test":"./node_modules/.bin/mocha test"
}
}

由于NPM脚本的唯一要求是可以在Shell中执行,因此它不一定是Node脚本,任何可执行文件都可以写在script中。NPM脚本的退出码也遵守Shell脚本规则,如果退出码不是0,NPM就认为该脚本执行失败。