作为前端开发,npm script 基本上每天都会用到,但是呢,很多同学可能都是只停留在run的层面,并没有去深入了解。今天笔者就来介绍一些不一样的npm script操作。希望能对小伙伴们有所帮助。
npm script其实我们每天都在使用,就是我们package.json文件scripts属性里面的语句。比如我们常用的npm run dev、npm run serve、npm start等等都是npm script。
首先我们在package.json文件新建一个test script,内容是输出hello randy:
然后我们运行npm run test,控制台可以看到:
至此我们的第一个npm script就运行成功啦。
在实际开发过程中可能会碰到多个命令一起启动的情况。比如我们前后端一起启动。
运行多个命令就会涉及到串行和并行问题了,下面笔者分开讲解。
串行实现方式也比较简单,只需要用 && 符号把多条 npm script 按先后顺序串起来即可。
"scripts": {
"frotend": "echo \"前端服务启动啦\"",
"server": "echo \"后端服务启动啦\"",
"all1": "npm run frotend && npm run server",
},
运行结果如下:
需要注意的是,串行执行的时候如果前序命令失败,后续全部命令都会终止。
有时为了提高效率,我们希望多个命令并行执行,只需要用 & 符号把多条 npm script 按先后顺序串起来即可。
"scripts": {
"frotend": "echo \"前端服务启动啦\"",
"server": "echo \"后端服务启动啦\"",
"all2": "npm run frotend & npm run server",
},
运行结果如下:
其实除了使用&& 和 &,我们还有更优雅的方式,可以使用npm-run-all或concurrently。
首先我们来安装:
npm i npm-run-all -D
然后添加我们的npm-run-all命令:
"scripts": {
"frotend": "echo \"前端服务启动啦\"",
"server": "echo \"后端服务启动啦\"",
"all3": "npm-run-all frotend server",
},
运行结果如下:
上面是串行执行的,当然我们也可以并行执行,只需要加上--parallel:
"scripts": {
"frotend": "echo \"前端服务启动啦\"",
"server": "echo \"后端服务启动啦\"",
"all4": "npm-run-all --parallel frotend server",
},
运行结果如下:
npm-run-all还有很多用法,这里只是一个入门,感兴趣的同学可以查看文档自行学习。
首先我们来安装:
npm i concurrently -D
然后添加我们的concurrently命令:
"scripts": {
"frotend": "echo \"前端服务启动啦\"",
"server": "echo \"后端服务启动啦\"",
"all5": "concurrently \"npm run frotend\" \"npm run server\""
},
运行结果如下:
concurrently还有很多用法,这里只是一个入门,感兴趣的同学可以查看文档自行学习。
eslint我们都知道,是前端开发代码检测的一个重要工具。我们经常配置两条script,一条用来检测错误,一条用来进行简单错误的修复。
"lint": "eslint js/*.js",
"lint:fix": "eslint js/*.js --fix"
笔者js文件夹下有这样一个js文件,它是空格问题。
我们运行npm run lint,可以看到如下错误:
空格这种简单问题eslint是可以自动修复的,我们运行npm run lint:fix可以看到,空格问题被自动修复了:
其实学习完npm script 传递参数后,我们一条命令就可以搞定了。
npm script使用--传递参数。
我们在package.json里面只需要配置一条命令:
"lint": "eslint js/*.js",
需要修复的时候我们通过传递参数的方式进行处理。
可以看到,空格问题也被自动修复了,其实它运行的就是eslint js/*.js --fix:
通过参数的方法可以大大减少我们script的数量,让script灵活度更高,特别是某些需要传递各种参数的script。
在运行 npm script 出现问题时你需要有能力去调试它,我们可以通过看日志来分析问题。日志级别是可以通过参数控制的。
即不加任何日志控制参数得到的输出,可能是你最常用的,能看到执行的命令、命令执行的结果。
比如笔者上面的例子:
如果需要显示更少日志,我们只需要在运行script的时候传递--loglevel silent或者 --silent或者更简单的 -s 来控制。
比如笔者上面的例子:
就只会输出结果,非常简单。
如果需要显示更多日志,我们只需要在运行script的时候传递--loglevel verbose或者 --verbose或者更简单的 -d 来控制。
比如笔者上面的例子:
可以看到,输出了非常多的信息。
为了方便开发者自定义,npm script 的设计者为命令的执行增加了类似生命周期的机制,具体来说就是 pre 和 post 钩子脚本。这种特性在某些操作前需要做检查、某些操作后需要做清理的情况下非常有用。
举例来说,运行 npm run test 的时候,分 3 个阶段:
还是上面代码检查的例子,我们创建三条命令:
"lint": "eslint js/*.js",
"prelint": "eslint js/*.js --fix",
"postlint": "echo \"eslint执行完毕\""
我们在每次lint前,自动进行代码修复,执行完lint后输出eslint执行完毕。我们来看下效果:
我们只执行了npm run lint,但是它执行了npm run prelint、npm run lint、npm run postlint三条命令。
npm script 可以使用预定义变量和自定义变量。
预定义变量其实就是解析整个package.json文件获取各个字段和值。
通过运行 npm run env 就能拿到完整的变量列表,这个列表非常长,这里我使用 npm run env | grep npm_package | sort 拿到部分排序后的预定义变量:
笔者的文件如下:
变量的使用方法遵循 shell 里面的语法,直接在 npm script 给想要引用的变量前面加上 $ 符号即可。
"var1": "echo $npm_package_author_name"
执行npm run var1,运行结果如下:
除了预定义变量外,我们还可以在 package.json 中添加自定义变量,并且在 npm script 中使用这些变量。
自定义变量需要配置在package.json里面config字段里。
{
"config": { "say": "hello randy" },
}
使用跟预定义变量一样,在变量前面加上 $ 符号即可。
"var2": "echo $npm_package_config_say"
执行npm run var2,运行结果如下:
注意 Linux、Mac 下直接可以用 $npm_package_name,而 Windows 下必须使用 %npm_package_name%。
前面说到Linux、Mac和Windows引用变量的方式是不同的。
可能有部分同学处理过 npm script 跨平台兼容的问题,比如粗暴的为两种平台各写一份 npm script,像下面这样:
{
"name": "test",
"scripts": {
"bash-script": "echo Hello $npm_package_name",
"win-script": "echo Hello %npm_package_name%"
}
}
那有没有什么更好的办法来实现呢?
cross-var就是用来解决跨平台变量使用问题的。
首先我们安装 cross-var:
npm i cross-var -D
然后修改我们的命令:
"var3": "cross-var echo %npm_package_config_say%",
"var4": "cross-var echo $npm_package_config_say"
我们来看下运行结果:
笔者是mac,可以看到,使用windows的方式引用变量也是能正常运行的。这就是cross-var的魅力。
有写小伙伴可能会说啦,变量平时使用的不多,环境变量倒使用的不少,那有什么跨平台使用环境变量的方式吗?
cross-env是用来解决跨平台环境变量问题的。
首先我们安装 cross-env:
npm i cross-env -D
然后我们在设置环境变量的时候,加上cross-env就可以了。
"env1": "cross-env NODE_ENV=staging"
这样环境变量也可以跨平台使用了。
对于一个新项目,如果想要知道它有哪些script我们一般都会找到package.json文件,然后查看它scripts字段。其实还有更简单的方法,直接在项目目录下执行npm run 就能列出 scripts 对象中定义的所有命令。
这样是不是很爽呢。
npm run xxx的时候,首先会去项目的package.json文件里找 scripts 里找对应的xxx,然后执行 xxx 的命令,例如启动vue项目 npm run serve的时候,实际上就是执行了vue-cli-service serve 这条命令。
为什么不直接执行vue-cli-service serve而要执行npm run serve 呢?
因为 直接执行vue-cli-service serve,会报错,因为操作系统中没有存在vue-cli-service这一条指令。
那既然vue-cli-service这条指令不存在操作系统中,为什么执行npm run serve的时候,也就是相当于执行了vue-cli-service serve ,为什么这样它就能成功,而且不报指令不存在的错误呢?
这就需要了解npm run xxx是怎么查找命令的啦:
因为我们在安装依赖的时候,是通过npm i xxx 来执行的,例如 npm i @vue/cli-service,npm 在安装这个依赖的时候,就会在node_modules/.bin/ 目录中创建好vue-cli-service 为名的几个可执行文件了。
所以当使用 npm run serve 执行 vue-cli-service serve 时,npm 会到 ./node_modules/.bin 中找到 vue-cli-service 文件作为脚本来执行,则相当于执行了 ./node_modules/.bin/vue-cli-service serve。
有时我们可以全局安装,例如npm i -g @vue/cli-service,这样他会在全局的node_modules/.bin中创建可以执行程序,所以我们在电脑的任何目录下都能运行对应的命令。
好了,感谢小伙伴们的耐心观看,关于npm script今天就讲到这里。