npm除了管理第三方模块外,还是一个任务管理器。开发者可以在pacakge.json的script字段中自定义命令,然后使用npm run命令来运行。
// 假设项目主文件是main.js,而它接受很多参数 $ node main.js 1 2 3 4 ...
每次在控制台输入完整的命令很不方便,此时可以把命令放在script字段中。
// package.json script:{ "start": " node main.js 1 2 3 4 ..." } // 运行 $ npm start // 或者 $ npm run start
使用npm run命令可以运行定义在scripts字段中的命令,其中npm test、npm start、npm restart,以及npm stop是对应npm run xxx的简写。
script字段中还可以定义任何可以在控制台中使用的命令。例如,定义一个用于清除当前文件夹下.log文件的clean命令。
script:{ "clean": "rm -rf *.log" } // 运行 $ npm run clean
使用npm命令构建的另外一个好处就是,不需要全局安装某个模块,假设在package.json文件中有如下配置。
"scripts": { "start": "ng serve", "test": "jasmine", }
从图2-2中可以看出,node_modules文件夹下除了安装的第三方模块外,还有一个.bin文件夹,该文件夹用于存放第三方模块提供的命令行工具,如图2-4所示。一些第三方模块(如gulp、jasmine、angular-cli模块)会附带一些可执行文件,如gulp.cmd、jasmine.cmd、ng.cmd等。
图2-4 安装jasmine模块后.bin目录的内容
当在控制台中运行npm start或者npm test的时候,npm会首先从node_modules中的.bin目录里寻找对应的可执行文件。如果没有找到,再去系统的环境变量中查找。
这样带来的好处有两点。第一点是避免了Node项目依赖全局的某些模块,确保只依靠package.json中描述的依赖就可以运行一个Node项目。第二点就是避免有些全局模块和node_modules中模块的版本不兼容。一个典型的例子就是angular-cli模块,ng serve命令用于运行一个Angular项目,但由于Angular火箭一样的版本升级速度,经常出现全局环境中的angular-cli工具和package.json中的angular模块版本不兼容的情况。
笔者有段实际的经历,曾经有位出名的Angular社区讲师来到公司里进行Angular培训,接到通知的笔者以及同事们早早地准备好了开发环境(全局环境下最新的angular-cli),然后那位讲师提供了GitHub上的示例代码。
获得示例代码后,笔者在命令行中运行npm install,安装完成后再运行ng serve,无一例外地编译失败。经过检查后发现示例代码中的angular模块版本比较低,而高版本的angular-cli不兼容低版本的angular模块。这时只要在package.json中配置npm start命令,就可以避免这个问题。