npm script
在package.json
文件中有一个scripts
属性,定义了包括各生命周期的脚本命令和自定义脚本。
1.使用
我们可以使用npm run <stage>
运行已定义的脚本命令,这个命令会同时运行pre-
post-
这两个钩子脚本,执行顺序为:per-
,命令本身,post-
。
npm 有一些默认的脚本:
"start": "node server.js" // 如果项目中根目录存在server.js
"install": "node-gyp rebuild" // 如果项目中根目录存在文件binding.gyp,npm会默认使用node-gyp编译安装命令
2.原理
当运行npm run -
脚本命令时会新建一个shell
命令,并且将当前目录的node_module/.bin
文件路径添加到path
变量下,运行结束后path
变量恢复原样。


安装第三方带有bin
字段的npm
文件,可执行文件会被链接到node_module/.bin
中,所以我们可以在scripts
中执行安装的npm
包命令。

"start": "nodemon" // 等同于 “./node_module/.bin/nodemon”
3.执行顺序
运行多个任务脚本一般有串行和并行
{
"scripts": {
"clean": "rimraf dist",
"lint": "eslint src",
"build": "babel src -o lib"
}
}
并行(同时执行,互不干扰):
npm run lint & npm run build
串行(前一个任务执行成功,再执行下一个任务):
npm run clean && npm run lint && npm run build
还可以使用npm-run-all
CLI 工具执行并行或顺序运行多个 npm 脚本。
并行:
run-p lint build 或者 npm-run-all --parallel lint build
串行:
run-s clean lint build 或者 npm-run-all clean lint build
4.钩子
prepublish
:在npm publish
命令之前运行publish,postpublish
: 在npm publish
命令后执行preinstall
: 在npm install
命令前执行install,postinstall
: 在npm install
命令后执行preuninstall,uninstall
: 在npm uninstall
命令前执行postuninstall
: 在npm uninstall
命令后执行preversion
:在改变包的version前执行version
: 在改变包的version后,但提交之前执行postversion
: 在提交version变更后执行pretest, test, posttest
: 伴随npm test
命令prestop, stop, poststop
: 伴随npm stop
命令restart, start, poststart
: 伴随npm start
命令pre restart, restart, poststart
: 伴随npm restart
命令。提示:假如scripts里没有写restart命令,npm默认会运行start、stoppreshrinkwrap, shrinkwrap, postshrinkwrap
: 伴随npm shrinkwrap
命令(用于固定依赖包版本)
另外,所有的script都可以用
npm run-script <stage>
命令执行, pre 和 post 会自动匹配对应的script(例如premyscript,my script, postmyscript
),依赖包中的script可以用npm explore <pkg> -- npm run <stage>
来执行
5.传参
向 npm 脚本传入参数,要使用--
标明。
npm run test -- --grep="pattern"
参数将只传递给 npm 运行后指定的脚本,而不传递给任何前脚本或后脚本。
6.环境变量
package.json变量
package.json的属性名会拼接上npm_package_
前缀。例如如果你的package.json文件中有{“name”:“foo”,“version”:“1.2.5”})
,那么你的脚本中npm_package_name
会是foo
,而npm_package_version
会是1.2.5
config
如果npm config中存在<name> [@ <version>]:<key>的配置参数,则package.json里config对应的key将在环境中被覆盖。例如,如果package.json有这样的:
{
"name" : "foo",
"config" : { "port" : "8080" },
"scripts" : {
"start" : "node server.js"
}
}
而server.js中这么写:
http.createServer(...).listen(process.env.npm_package_config_port)
那么用户可以这样覆写:
npm config set foo:port 80
当前的生命周期事件
最后,npm_lifecycle_event
环境变量代表当前执行循环的哪个阶段。所以,你可以使用单个脚本用于根据当前正在发生的事件切换的进程的不同部分。
对象按照层级以下划线连接,如果您的package.json中有
{“scripts”:{“install”:“foo.js”}}
则可以在脚本中看到:
process.env.npm_package_scripts_install === "foo.js"
假如你的package.json有如下设置:
{ "scripts" :
{
"install" : "scripts/install.js",
"postinstall" : "scripts/install.js",
"uninstall" : "scripts/uninstall.js"
}
}
那么在生命周期的install
和postinstall
阶段将调用scripts/install.js
,在uninstall
时将会调用scripts/uninstall.js
。
由于scripts/install.js
在两个不同的阶段都有运行,因此在这种情况下,查看npm_lifecycle_event
变量是聪明的做法。
如果你想要运行make命令也没问题,这样写:
{ "scripts" :
{
"preinstall" : "./configure",
"install" : "make && make install",
"test" : "make test"
}
}