目录
- 引言
- 1.什么是npm脚本?
- 2.原则
- 3.通配符
- 4.传递参数
- 5.执行顺序
- 6.默认值
- 7.钩子
- 8.缩写形式
- 9.变量
- 10.常见脚本示例
- 11.使用nrm管理npm镜像
引言
使用Node进行开发时,必须使用npm,脚本是npm的最强大和最常见的功能之一。
我将在本文中介绍如何使用npm脚本。
1.什么是npm脚本?
Npm允许您使用文件中的scripts
字段定义脚本命令package.json
。
{
// ...
"scripts": {
"build": "node build.js"
}
}
上面的代码是package.json
文件的一部分,scripts
这里的字段是一个对象。它的每个属性都对应一个脚本。例如,与该build
命令对应的脚本为node build.js
。
如果您npm run
在命令行下使用该命令,脚本将被执行。
$ npm run build
# equivalent to execution
$ node build.js
在中定义的这些脚本package.json
称为npm脚本。有很多优点:
- 与项目相关的脚本可以放在一个地方。
- 用于不同项目的脚本命令可以使用相同的外部接口,只要它们具有相同的功能即可。用户不需要知道如何测试您的项目,只需运行npm run test即可。
- 您可以利用npm提供的许多辅助功能。
您可以使用npm run
不带任何参数的命令来查看当前项目的所有npm脚本命令。
$ npm run
2.原则
npm脚本的原理非常简单。无论何时npm run
执行,都会自动创建一个新的shell,并且将在该shell中执行指定的脚本命令。因此,只要该命令可以由外壳程序(通常是Bash)运行,它就可以用npm脚本编写。
特殊的是,由创建的shell npm run
将node_modules/.bin
当前目录的子目录添加到PATH
变量中,并且该PATH
变量将在执行后恢复。
这意味着可以直接通过脚本名称来调用当前目录的node_modules / .bin子目录中的所有脚本,而无需添加路径。例如,如果当前项目的依赖项中包含Mocha,则只需mocha test
直接编写:
"test": "mocha test"
而不是像这样写:
"test": "./node_modules/.bin/mocha test"
由于对npm脚本的唯一要求是脚本可以在shell中执行,因此它们不一定是Node脚本,并且可以在其中编写任何可执行文件。
npm脚本的退出代码也遵循shell脚本的规则。如果退出代码不是0
,则npm将假定脚本执行失败。
3.通配符
由于npm脚本是Shell脚本,因此可以使用Shell通配符。
"lint": "jshint *.js"
"lint": "jshint **/*.js"
在上面的代码中,*
表示任何文件名,**
表示任何子目录。
如果要将通配符传递给原始命令以防止被Shell逸出,则必须逸出星号。
"test": "tap test/\*.js"
4.传递参数
使用--
指示传递给npm脚本的参数。
"lint": "jshint **.js"
如果将参数传递给上述npm run lint命令,则必须编写如下。
$ npm run lint -- --reporter checkstyle > checkstyle.xml
您也可以在中再次封装命令package.json
。
"lint": "jshint **.js",
"lint:checkstyle": "npm run lint -- --reporter checkstyle > checkstyle.xml"
5.执行顺序
如果要在npm脚本中执行多个任务,则需要弄清执行顺序。
如果是并行执行(并行并行执行),则可以使用&符号。
$ npm run script1.js & npm run script2.js
如果是顺序执行(仅在成功执行前一个任务时才执行下一个任务),则可以使用该&&
符号。
$ npm run script1.js && npm run script2.js
这两个符号是Bash的功能。另外,您可以使用节点的任务管理模块:script-runner,npm-run-all,redrun。
6.默认值
通常,npm脚本由用户提供。但是,npm为两个脚本提供了默认值。换句话说,这两个脚本无需定义即可直接使用。
"start": "node server.js",
"install": "node-gyp rebuild"
在上述代码中,默认值npm run start
是node server.js
,提供有一个server.js
在项目的根目录脚本; 默认值npm run install
就是node-gyp rebuild
,只要有一个binding.gyp
项目的根目录下的文件。
7.钩子
npm脚本有两个钩子:pre
和post
。例如,build
脚本命令的挂钩是prebuild
和postbuild
。
"prebuild": "echo I run before the build script",
"build": "cross-env NODE_ENV=production webpack",
"postbuild": "echo I run after the build script
当用户执行时,它将按以下顺序自动执行npm run build
。
npm run prebuild && npm run build && npm run postbuild
因此,可以在这两个挂钩中进行一些准备和清理。这是下面的例子。
"clean": "rimraf ./dist && mkdir dist",
"prebuild": "npm run clean",
"build": "cross-env NODE_ENV=production webpack"
Npm默认提供以下钩子:
- 预发布,后发布
- 预安装,后安装
- preuninstall,postuninstall
- 前版本,后版本
- 前测,后测
- 穿越,后停
- 启动前,记录开始
- 重启前,重启后
自定义脚本命令也可以与pre
和post
挂钩一起添加。例如,脚本命令myscript
具有premyscript
和postmyscript
钩子。但是,double pres和posts无效。例如,prepretest
和postposttest
是无效的。
在npm_lifecycle_event
由npm提供的变量返回当前运行的脚本的名称,如pretest
,test
,posttest
,等。因此,您可以使用该变量为npm scripts
同一脚本文件中的不同命令编写代码。让我们看下面的例子。
const TARGET = process.env.npm_lifecycle_event;
if (TARGET === 'test') {
console.log('Running the test task!');
}
if (TARGET === 'pretest') {
console.log('Running the pretest task!');
}
if (TARGET === 'posttest') {
console.log('Running the posttest task!');
}
❝ 请注意,prepublish挂钩不仅将在npm publish命令之前运行,而且还将在npm install(不带任何参数)命令之前运行。但是,这种行为很容易使用户感到困惑,因此npm 4引入了一个prepare行为类似于的新钩子prepublish。从npm 5开始,该prepublish钩子只会在npm publish命令之前运行。 ❞
8.缩写形式
这是四个常用npm脚本的简短版本。
npm start 是短的 npm run start
npm stop 是短的 npm run stop
npm test 是短的 npm run test
npm restart 是短的 npm run stop && npm run restart && npm run start
npm start
,npm stop
和npm restart
都是很好的理解,而npm restart
是实际执行三个脚本命令的化合物命令:stop
,restart
,start
。并且执行顺序如下。
- 重新启动
- 调动
- 停
- 邮件停止
- 重新开始
- 预启动
- 开始
- 邮件开始
- 重启后
9.变量
npm脚本具有非常强大的功能,可让您使用npm的内部变量。
首先,npm脚本可以获取package.json
带有npm_package_
前缀的字段。例如,package.json
下面是一个。
{
"name": "foo",
"version": "1.2.5",
"scripts": {
"view": "node view.js"
}
}
然后,该变量npm_package_name返回foo
,并且该变量npm_package_version
返回1.2.5
。
// view.js
console.log(process.env.npm_package_name); // foo
console.log(process.env.npm_package_version); // 1.2.5
在上面的代码中,我们package.json
通过环境变量process.env
对象获取的字段值。如果是Bash
脚本,则可以使用$npm_package_name
和获得两个值$npm_package_version
。
该 npm_package_
前缀也支持嵌套的package.json
领域。
"repository": {
"type": "git",
"url": "xxx"
},
scripts: {
"view": "echo $npm_package_repository_type"
}
在上面的代码中,您可以使用获取字段的type
属性。repositorynpm_package_repository_type
这是另一个例子。
"scripts": {
"install": "foo.js"
}
在上面的代码中,npm_package_scripts_install
变量的值等于foo.js
。
npm config get xxx
也可以通过npm_config_
前缀获取npm的配置变量(命令返回的值)。例如,您可以使用获取当前模块的release
标签npm_config_tag
。
"view": "echo $npm_config_tag",
请注意,环境变量可以覆盖中的config对象package.json。
{
"name" : "foo",
"config" : { "port" : "8080" },
"scripts" : { "start" : "node server.js" }
}
在上面的代码中,npm_package_config_port变量返回8080。并且可以通过以下方法覆盖此值。
$ npm config set foo:port 80
env命令可以列出所有环境变量。
"env": "env"
10.常见脚本示例
// delete the directory
"clean": "rimraf dist/*",
// build an HTTP service locally
"serve": "http-server -p 9090 dist/",
// open the browser
"open:dev": "opener http://localhost:9090",
// real-time refresh
"livereload": "live-reload --port 9091 dist/",
// build an HTML file
"build:html": "jade index.jade > dist/index.html",
// Re-execute the build as long as the CSS file has changed.
"watch:css": "watch 'npm run build:css' assets/styles/",
// Re-execute the build as long as the HTML file has changed
"watch:html": "watch 'npm run build:html' assets/html",
// Deploy to Amazon S3.
"deploy:prod": "s3-cli sync ./dist/ s3://example-com/prod-site/",
// build favicon
"build:favicon": "node scripts/favicon.js",
11.使用nrm管理npm镜像
nrm(npm registry manager)是npm的镜像源管理工具,有时候国外资源太慢,使用这个就可以快速地在 npm 源间切换。
在命令行执行以下命令,全局安装nrm
。
npm install -g nrm
执行命令nrm ls
查看可选的源。
其中,带*
的是当前使用的源,上面的输出表明当前源是taobao源。
如果要切换到cnpm源或者其他镜像,您可以使用nrm use 源名称
进行切换:
nrm use cnpm
你可以增加定制的源,特别适用于添加企业内部的私有源,执行命令nrm add <registry> <url>
,其中reigstry为源名,url为源的路径。
nrm add registry http://registry.npm.frp.trmap.cn/
删除,执行以下命令:
nrm del <registry> url
你还可以通过 nrm test
测试相应源的响应时间,从而决定使用哪种镜像!
nrm test taobao