本文翻译自npm官方script文档javascript
npm 支持运行package.json里“scripts”属性中的脚本,包括:java
prepublish
:在npm publish
命令以前运行(也会在不带参数的npm install
命令前运行,详情在下段描述)node
prepare
: 在两种状况前运行,一是npm publish
命令前,二是不带参数的npm install
命令;它会在prepublish
以后、prepublishOnly
以前执行git
prepublishOnly
: 在npm publish
命令前执行github
publish,postpublish
: 在npm publish
命令后执行npm
preinstall
: 在npm install
命令前执行json
install,postinstall
: 在npm install
命令后执行curl
preuninstall,uninstall
: 在npm uninstall
命令前执行工具
postuninstall
: 在npm uninstall
命令后执行post
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、stop
preshrinkwrap, shrinkwrap, postshrinkwrap
: 伴随 npm shrinkwrap
命令(用于固定依赖包版本)
另外,全部的script均可以用 npm run-script <stage>
命令执行, pre 和 post 会自动匹配对应的script(例如 premyscript,my script, postmyscript
),依赖包中的script能够用npm explore <pkg> -- npm run <stage>
来执行
从npm@1.1.71开始,npm CLI 会在npm publish
和npm install
以前执行prepubish
脚本,由于这作法便于准备package环境(几种用法如本段下面描述)。但事实证实这让人很是困惑。因此在npm@4.0.0后,新增来一种事件prepare
来替代上述功能。另一种新事件prepublishOnly
做为替代策略,让用户避免以往npm版本的混乱行为。prepublishOnly
只在npm publish
前执行(例如,publish前最后执行一次测试,以确保无误)
重要提示:在npm5中, prepublish
只在npm publish
前执行,即取代prepublishOnly
,因此npm6即之后的版本会放弃prepublishOnly
。到时就忘了这些矬事吧。
https://github.com/npm/npm/issues/10074 ,这里对此变动有过漫长的争论可做参考。
若是你须要在使用package以前执行某些操做,而不依赖于目标系统的操做系统或目录结构,请使用prepublish脚本。例如如下任务:
把coffeescript源码编译成JS
压缩js源码
获取你的package所需的远程资源
在publish时作这些事情的好处是,它们能够在同一处完成,从而下降复杂性和差别性。另外,这意味着:
你能够依赖于coffee-script做为devDependency,但你的用户不须要安装它。
你不须要在包中包含min版本,以节省空间
你的用户的电脑上没必要具备curl或wget或其余系统工具
npm 预设了几个script内容:
"start": "node server.js"
若是你的package根目录中有server.js, npm会默认以之做为start命令执行。
"install": "node-gyp rebuild"
若是你的package根目录下中有binding.gyp而你又没定义 install或preinstall脚本,npm会默认以npm-gyp编译。
若是使用root权限调用npm,那么它会将uid更改成用户配置指定的uid,默认为nobody。设置unsafe-perm以使用root权限运行脚本。
npm 脚本运行在 npm的设置和进程的当前状态 的环境中。(不知道怎么翻)
Package scripts run in an environment where many pieces of information are made available regarding the setup of npm and the current state of the process.
若是你依赖的模块(如测试模块)定义了可执行脚本,那么这些可执行文件将被添加到PATH中执行。因此,若是你的package.json有这样的依赖:
{ "name" : "foo", "dependencies" : { "bar" : "0.1.x" }, "scripts": { "start" : "bar ./test" } }
那么在你npm install
时,bar会导进node_modules/.bin
目录中,你能够运行npm start
执行 bar脚本。
package.json的属性名会拼接上npm_package_
前缀。例如若是你的package.json文件中有{“name”:“foo”,“version”:“1.2.5”})
,那么你的脚本中npm_package_name
会是foo
,而npm_package_version
会是1.2.5
使用npm_config_
前缀将配置参数放在环境中。例如你能够经过检查npm_config_root
环境变量来查看目前生效的root配置。
特殊:package.json中的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)
那么用户能够这样覆写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" } }
npm脚本是经过将该行做为脚本参数传给sh来运行的。
若是脚本不是以退出码0退出,则会停止该进程。
请注意,这些脚本文件没必要是nodejs甚至是javascript程序。他们只须要一些可执行文件。
若是要为全部package在某生命周期事件中运行某脚本,则可使用钩子脚本。
在node_modules/.hooks/{eventname}
中放置一个可执行文件,全部装在根目录下的package在运行到该生命周期节点时都会执行。
Hook脚本的运行方式与package.json里的脚本彻底相同。也就是说,它们与上述env在一个单独的子进程中。
不要以0之外的错误码退出,除非你真的想这样作。由于这将致使npm操做失败(install
脚本除外),并可能会回滚。若是这个错误可有可无或只会阻断一些小功能,那么最好只是输出一个警告,让线程成功退出。
尽可能不要使用npm脚原本作npm自己就能够作的事情。通读package.json文件,你能够学到全部经过简单、合适的配置来具体描述你的package。这一般更健壮和通用。
经过检查env
来决定把东西装在哪。例如,若是npm_config_binroot
环境变量设置为/home/user/bin
,那么不要尝试将可执行文件安装到/usr/local/bin
中。用户可能由于某种缘由设置了这种方式。
不要在脚本命令里加sudo
前缀。若是因为某些缘由须要root权限,不然会报错;那么用户应该考虑以sudo运行npm命令。
不要使用install
脚本。使用.gyp
文件进行编译,其余状况则使用prepublish
。你最好永远不要自定义preinstall
或install
脚本。若是你要这样作,请优先考虑是否有其余办法。install
或preinstall
脚本的惟一正确使用场景是用做设置那些编译的目标目录。