众所周知,npm
是工程师们基于nodejs
的开发中的核心内容。而大部分人在使用npm
时,主要使用她的包管理系统。
但是,当我们稍微look look那些知名的开源项目,或者老牛们的代码时,常常都能在它们的package.json
里看到一个写满了命令的scripts
属性。这里面都隐藏了哪些秘密,牛牛们都用它做了什么,怎么做到的?这些疑问必定撕扯着你的好奇心,来,我们今天就聊聊神秘的scripts
属性。
Hooks(钩子)
通常情况下,应用程序只能处理来自内部的消息,如果希望对外部发来的消息也能拦截处理,那就需要一种叫钩子(Hook)的技术。想象一下,npm test
这个过程你是控制不了的,但如果就非常想在test
之前自动处理点什么事儿,怎么办?没次都手动在test
之前执行什么,烦不烦、烦不烦、烦不烦?就是不烦,也会忘啊!
这时候就用到我们的Hook了。下面这些指令都是Hook,它们都可以在package.json
的scripts
属性里定义,并且会在生命周期的某个指定时刻被执行,这就是上面提到的“对外部发来的消息也能拦截处理”,这极大的方便了开发人员(或许你想做点坏事儿?)
prepublish
: 在publish
该包之前执行。(在包目录下执行npm install
时也会执行)postpublish
: 在该包publish
之后执行preinstall
: 在该包被install
之前执行postinstall
: 在该包被install
之后执行preuninstall
: 在该包被uninstall
之前执行postuninstall
: 在该包被uninstall
之后执行preversion
: 在修改该包的version
之前执行postversion
: 在修改该包的version
之后执行pretest
,posttest
: 在该包内执行test
时执行,其中pretest
先于posttest
prestop
,poststop
: 在该包内执行stop
时执行,其中prestop
先于poststop
prestart
,poststart
: 在该包内执行start
时执行,其中prestart
先于poststart
prerestart
,postrestart
: 在该包内执行restart
脚本时执行,其中prerestart
先于postrestart
。注意: 如果没有在scripts
里显示指定restart
脚本,则会自动调用stop
,然后再start
上面这些Hooks都是npm
预定义好的,也就是说,当你执行npm install
时,如果你在scripts
里定义了preinstall
和postinstall
,那它们分别会在npm install
之前/后自动执行,不劳你操心!碉堡了,有木有?
还有,任何自定义脚本(通过npm run-script <脚本名>
来执行)也可以前缀pre
和post
为其制作钩子。比如:premyscript
,myscript
,postmyscript
注:也可以使用
run
作为run-script
的简写使用。
说说常见的使用场景1
如果你写了一个类库,有些操作和操作系统无关,但却希望在该包被使用前执行,可以试试prepublish
,意思是,在你执行npm publish
的时候,自动先执行scripts
里定义的prepublish
里的脚本。
举个栗子:假设我用CoffeeScript
写了一个类库,我有下面两个愿望:
我希望发布的是
JavaScript
版本,这样用户npm install <类库>
之后无需搭建神马乱七八糟的环境,即可直接使用我希望发布的是一个minified版本,即用户
npm install <类库>
之后,也可直接引入使用,而不必关心还要帮我压缩一次
OK,我们现在来聊聊这里我用prepublish
的好处:
这事儿执行一次就够,就是我
publish
包的时候,不需要神马用户每次install
的时候也做coffee-script
可以作为devDependencies
在我的项目里,这样的话,用户在install
这个类库的时候,就不会下载coffee-script
了。uglify-js
也可以作为devDependencies
在我的项目里,好处同上
说说常见的使用场景2
再比如,写了一个类库,其中有些操作是和操作系统相关的,可以使用postinstall
看看。
那我之前写的一个movoto-cli举例,我有一个期望:
用户在install
我的类库后,这个类库要将两个配置文件eslintrc_browser_legacy.json
和eslintrc_node.json
里的LINEBREAK_OS
字段根据用户的操作系统修改为正确的值。
于是我把这个操作写在了postinstall
这个Hook里,问题解决,完美,没问题!
Environment
经常听到有朋友问到这样的问题,说看到有人的scripts
里写了"test": "mocha --reporter nyan"
,觉得这个代码有漏洞,使用这个指令的人,必须得先npm install -g mocha
(全局安装mocha
),否则test
命令找不到mocha
,会报错的吧!
答案是这样的,一般这么写scripts
的,通常会把mocha
装在devDependencies
或者dependencies
里。scripts
里的指令有这样一个特点,如果你的类库(或叫模块)依赖的其它模块提供了可执行脚本(譬如:mocha
),那这些依赖会在你执行scripts
指令时自动被注入到执行进程的PATH
里。
这就是说,如果devDependencies
或者dependencies
里有mocha
,那在npm test
的时候,里面的mocha
命令,是从注入的PATH
里(即:node_modules/.bin/mocha
)找了。
So,还需要全局安装mocha
么?恐怕不需要了^^
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。