什么是npmscript?npmscript是一些自定义的脚本,记录在package.json的scripts字段中。使用自定义脚本,用户可以将一些项目中常用的命令行记录在package.json中,每次都需要敲一下。需要开发者经常需要使用如下命令来统计项目中的代码行数:findsrc-name"*.js"|xargs猫|wc-l开发者可以写入package.json:"scripts":{"lines":"findsrc-name\"*.js\"|xargscat|wc-l",}以后开发者只需要执行npmrunlines而不是写这么长的命令行,可以大大提高效率。需要注意的是,因为命令写在json文件中,所以有些特殊字符需要翻译,比如上面的双引号。环境变量PATHnpmscripts并不是简单的执行shell语句,它会在执行前将node_modules/.bin/添加到环境变量PATH中,所以node_modules/.bin/中的可以直接在npmscripts可执行文件中使用。很多使用mocha作为测试框架的项目都有这样一个npm脚本"scripts":{"test":"mocha"}mocha并没有全局安装,它的命令行工具存在于node_modules/.bin/中。之所以能够访问到,正是因为npm背后的运行,使得此类命令能够正常执行。npm脚本执行后,将从PATH中移除。在执行npmruntest时(后面会看到这个可以简写为npmtest),相当于:./node_modules/.bin/mocha传入参数对于上面的脚本“test”:“mocha”如果你想通过mocha输入一些选项,比如你要执行:mocha--reporterspec需要这样执行npmtest:npmtest----reporterspec需要用两个短行分隔选项,或者写选项直接在package.json:"scripts":{"test":"mocha--reporterspec"}shell中传入的参数必须用--隔开,这个--视为npmrun命令的结束参数,以及--后面的内容将原封不动地移到正在运行的命令中。钩子脚本npm脚本中有两个钩子,pre和post。以上面的lines脚本为例,它的hook脚本是prelines和postlines"scripts":{"prelines":"nodeprelines.js""lines":"findsrc-name\"*.js\"|xargscat|wc-l","postlines":"nodepostlines"}执行npmrunlines,它会先执行prelines,然后执行lines,再执行postlines。还有一些生命周期事件中的脚本,会在模块的安装、发布、卸载等不同的生命周期中执行。prepublish、publish、postpublish:发布模块preinstall、install、postinstall:安装模块preuninstall、uninstall、postuninstall:卸载模块preversion、version、postversion:执行pretest、test、posttest:使用npmversion修改版本号时执行npmtestprestop、stop、poststop:执行npmstop时prestart、start、poststart:执行npmstart时prerestart、restart、postrestart:执行npmrestart时,这些脚本会在不同的时间自动执行,这就是为什么npmrun要测试的原因可以简写为npmtest,就是在执行npmtest的时候,会依次执行pretest、test、posttest。当然,如果前测和后测没有指定,它们将被静默跳过。还有npmrestart命令,比较坑爹。它不仅会执行prerestart、restart、postrestart这三个,而是按照以下顺序执行:prerestartprestopstoppoststopprestartprestartstartpoststartpostrestart环境变量在执行npmscript的时候还可以访问一些特殊的环境变量。package.json中的内容可以通过process.env.npm_package_xxx获取。例如process.env.npm_package_name可以得到package.json中name的值“sv”。{"name":"sv","version":"1.3.0","description":"","main":"index.js","repository":{"type":"git","url":"git+ssh://git@gitlab.com/wy-ei/sv.git"}}你可以通过process.env.npm_package_repository_type获取值"git"。另外可以通过process.env.npm_config_xxx获取npmconfig中的值。例如user.email的值可以通过process.env.npm_config_user_email获取。还有一个特殊的环境变量process.env.npm_lifecycle_event。当执行不同的npm脚本时,这个值是不同的。比如执行npmrunbuild时,这个值为build。通过判断这个变量,一个脚本在不同的npm脚本中使用。任何脚本语言编写的npm脚本都可以获取环境变量。比如你想在shell中获取,只需要使用$npm_config_user_email。不同的脚本需要使用各自的获取环境变量的方法来读取环境变量。另外,这些环境变量只有在执行npm脚本时才能获取到,正常执行的node脚本是获取不到的。写node命令行工具经常会用到npmscript中一些模块中的可执行程序,比如eslint、webpack等,那么如何自己写一个命令行工具,以便在npmscript中调用。1.编写命令行脚本,新建一个文件cli.js,并编写需要的逻辑。console.log("这篇文章很棒,不是吗?");2.在package.json的bin字段指定命令行文件名和路径{"bin":{"cli":"./cli.js"}}3.指定解释器用户安装后通过./node_modules/.bin/cli,会报错,因为当前的shell不知道用什么解释器来执行这些代码,所以需要在脚本解释器上面指定。#!usr/bin/envnodeconsole.log("这篇文章很棒,不是吗?");上面一行在所有的脚本文件中都可以看到,它叫做SheBang或者HashBang,见Shebang_(Unix)),这行代码告诉shell使用哪个解释器来执行代码。usr/bin/env是一个程序,usr/bin/envnode会在当前PATH中找到该节点来解释下面的代码。通过这三个步骤,开发了一个节点命令行工具。当用户安装这个模块时,npm会在node_modules/.bin/中创建一个文件,文件名为package.json中bin指定的命令名,并链接到相应的脚本。之后就可以在npmscript中使用了。多说几句,把上面的#!usr/bin/env节点写到JavaScript文件的第一行,就不会报错了。因为这是UNIX世界公认的东西。通过chmod+xcli.js,可以直接使用./cli.js执行,因为这一行已经告诉shell使用node来执行了。总结早在今年三月份,在网上看到了很多帖子,就有了一个观点,就是用npmscript代替gulp之类的构建工具。现在我们看到npmscript真的很强大。使用node和shell,我们可以编写一些非常实用的脚本,来解决手头的问题,不一定需要使用gulp和grunt之类的东西。据统计,2015年gulp以绝对优势占据taskrunner使用率第一,2016年npmscript使用率增长非常快。不管怎样,npmscript总会出现在你的日常工作中。希望这篇文章能帮助你了解npmscript,让npmscript帮助你加快开发效率。
