创建一个命令
我们正常编写js文件,然后在js文件的顶部加上这行注释#!/usr/bin/env node
,例如我们创建一个文件hello.js
文件,内容如下:
#!/usr/bin/env node
console.log('你好');
然后切换到hello.js
文件所在的目录,执行./hello.js
,会看到屏幕上打印了"你好",表明我们成功的创建了一个命令脚本
但是该方法还有一个欠缺,就是每次运行的时候还需要输入完整的路径,不够自动化,我们希望达到的效果是输入hello
命令,直接在屏幕上看到打印结果
$ hello
>> 你好
想要做到这个效果,我们需要在package.json
文件中增加bin
字段,注册一个命令(名称)和执行命令的脚本
{
"bin": {
"hello": "./bin/hello.js"
}
}
然后我们将这个包通过npm run publish
发布,然后我们安装这个包,如果是全局安装,则执行hello
之后就会看到打印结果,如果是安装在某个项目里,则需要用npx hello
命令查看效果
接下来我们探究下原理,以非全局安装为例,执行完npm install
之后,会自动生成一个文件夹 node_modules/.bin
,并在里面自动生成三个文件hello
、hello.cmd
、hello.ps1
,这三个文件的功能是一样的,都是执行对应的命令脚本,如hello
文件的内容是:
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
"$basedir/node" "$basedir/../hello/bin/hello.js" "$@"
ret=$?
else
node "$basedir/../hello/bin/hello.js" "$@"
ret=$?
fi
exit $ret
综上可知,如果我们想要创建一个命令,只需要两步:
- 在命令的执行脚本顶部加上
#!/usr/bin/env node
标记 - 在
package.json
文件里加上bin
字段,注册命令名称以及对应的命令脚本路径
关于参数的获取
命令行程序除了命令的注册外,命令参数的获取也是一个重要的环节,基本上关于命令行参数有这么几个基本的需求:
- 定义参数的数据类型
- 定义参数的默认值
- 获取用户配置的参数
- 参数的使用方法(实现--help)
- 参数别名(-n --name)
- 实现显示当前版本号功能
手动实现上述功能,主要是依赖对process.argv
的处理,上述的工作 Commander.js 已经帮我们做了实现,我们接下来介绍一下其用法
安装
npm install commander
配置version
const { program } = require('commander');
program.version('0.0.1');
const { Command } = require('commander');
const program = new Command();
program.version('0.0.1');
定义参数、获取参数
涉及到数据类型,必填项,默认值,别名,变长参数
-
数据类型:有两种最常用的选项,一类是 boolean 型选项,选项无需配置参数,另一类选项则可以设置参数(使用尖括号声明在该选项后,如--expect )。如果在命令行中不指定具体的选项及参数,则会被定义为undefined
-
必填:通过.requiredOption方法可以设置选项为必填。必填选项要么设有默认值,要么必须在命令行中输入,对应的属性字段在解析时必定会有赋值。该方法其余参数与.option一致
-
别名:每个选项可以定义一个简写名称(-后面接单个字符)和一个长选项名称(--后面接一个或多个单词),使用逗号、空格或|分隔,如
option('-d, --debug', 'output extra debugging')
-
变长参数:定义选项时,可以通过使用...来设置参数为可变长参数。在命令行中,用户可以输入多个参数,解析后会以数组形式存储在对应属性字段中,如
option('-l, --letter [letters...]', 'specify letters')
完整示例:
#!/usr/bin/env node
const commander = require('commander');
const program = new commander.Command();
program.version('0.0.1');
program
.option('-d, --debug', 'output extra debugging') // --debug 別名 -d
.requiredOption('-h, --hot', 'hot must chose') // 必填项
.option('-ad, --adress [adress...]', 'adress can mutl') // 必填项
.option('-s, --small', 'small pizza size', true)
.option('-p, --pizza-type <type>', 'flavour of pizza', 'okok');
program.parse(process.argv);
const options = program.opts();
console.log(options);
//
// $ ./cli-run.js -h -ad 123 32131 1321
// {
// small: true,
// pizzaType: 'okok',
// hot: true,
// adress: ['123', '32131', '1321']
// }
业界常见实现方式
通过上文可知,命令行的实际内容是个js
文件,只不过在package.json
里用bin
字段做了指定,以便可以在命令行中调取这个命令。在很多致命的第三方库,如webpack
、ESLint
,它们除了会提供API
调用方式外,还会提供命令行方式,基本上是在项目根目录添加一个bin
文件夹,实现连接命令与API
的脚本,向API
传递从命令行获取到的参数。所以基本上就是命令在API
的基础上做了一层获取参数的封装而已。
附录
参考文章
- 手把手教你写Node.js命令行程序
- Building a simple command line tool with npm :npm官方文章
- Node.js 命令行程序开发教程
必备开发包
- Commander.js :完整的Nodejs命令行程序解决方案,中文文档
- yargs:处理命令行参数
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!