Commander.js是node.js命令行界面的完整解决方案,受 Ruby Commander启发。(抄)
inquirer.js 开箱即用的交互式命令行工具
开始
- 新建一个node工程
- 执行
npm install commander
- package.json中新增代码
"bin": {
"clidemo": "./index.js"
// 版本上线后的全局命令名称
// 比如vue-cli是"vue": "bin/vue.js",即执行vue命令执行的文件
},
- 根目录下新建index.js文件,该文件中需在开始行编写
#! /usr/bin/env node
代码,用于识别是node命令文件
api
- 以下api基于
const program = require('commander')
- 其中大部分api都返回当前this
- 最后都假设执行了
program.parse(process.argv)
;通过program.parse(arguments)方法处理参数,没有被使用的选项会存放在program.args数组中。该方法的参数是可选的,默认值为process.argv。 - <item1> [item2] 尖括号表示item1必填 中括号表示item2选填,若括号内以...结束,则表示可传入多个参数
version
program.version('1.0.0', '-v, --version')
,其中第二个参数可以省略 具体代码如下
const program = require('commander')
const requiredPackageVersion = require('./package.json').version
program
.version(requiredPackageVersion)
.version(process.argv)
那么我们执行node index.js -V
,可以看到命令行展示了1.0.0,如果加上第二个参数'-v, --version'
,则应该执行node index.js -v
,展示结果与之前一致。改写了--version命令的简写方式。
option
- commander的重要命令之一
- 作用是添加命令以及命令的执行代码
- 查看api可以看到参数
option(flags: string, description?: string, defaultValue?: string | boolean): this;
option<T>(flags: string, description: string, fn: (value: string, previous: T) => T, defaultValue?: T): this;
option(flags: string, description: string, regexp: RegExp, defaultValue?: string | boolean): this;
flags表示命令的标识(必填),description为命令描述(可在--help中显示),fn为自定义命令方法,defaultValue为默认值
program
.option('-d, --drink [item]', 'output extra debugging', function deb (v) {
console.log('1---', arguments);
return '123'
})
.option('-s, --small', 'small pizza size')
.option('-p, --pizza-type <type>', 'flavour of pizza');
program.parse(process.argv);
输入命令node index.js -d 1234
,虽然打印了1234,但由于deb返回了123,最终我们使用的时候会使用123
command、action
- command用于配置命令,第一个参数可以配置命令名称及命令参数,参数支持必选(尖括号表示)、可选(方括号表示)及变长参数(点号表示,如果使用,只能是最后一个参数)
- action为执行命令的方法
program
.command('clone <source> [destination]')
.description('clone a repository into a newly created directory')
.action((source, destination) => {
console.log(source, destination);
console.log('clone command called');
});
program.parse(process.argv);
小demo
我们模仿vue/cli创建一个最简单的脚手架
- 新建node项目,配置好package.json的bin,假设我们配的是clidemo
- 安装包commander(命令行界面)、inquirer(交互式命令行工具)、download-git-repo(git本地克隆代码工具)、rimraf(文件校验工具)、文件操作工具建议使用fs-extra而非原生的fs,不过我们暂时先不用
新建index.js文件
#! /usr/bin/env node
const program = require('commander')
const { version } = require('./package.json')
const create = require('./utils/create')
program
.version(`scaffold ${version}`)
.usage('<command> [options]')
program
.command('create <app-name>')
.description('创建一个基于平台的新项目')
.option('-t, --typeName <typeName>', '基于哪个项目')
.action((name, options) => {
console.log(name, options);
create(name, options)
})
program.parse(process.argv)
新建文件/utils/create
const inquirer = require('inquirer')
const download = require("download-git-repo");
const path = require("path");
const rimraf = require("rimraf");
async function create (projectName, options) {
const resp = await inquirer.prompt([ // 问答环节
{
type: 'list',
name: 'typeName',
message: '你想使用什么项目?',
choices: ['umi', 'vue3'],
default: 1
},
{
type: 'expand',
name: 'test',
message: '测试expand',
choices: [{key: 'u', value: 'umi'}, {value: 'vue3', key: 'v'}],
default: 1
},
{
type: 'checkbox',
name: 'eslint',
message: '你想使用的代码校验方式?',
choices: [{value: 'aaa', checked: true}, 'eslint', 'prettier', 'typescript', {value: '123aaa', checked: true}],
},
{
type: 'input',
message: '您的手机号手机号:',
name: 'phone',
validate: function(val) {
if(val.match(/\d{11}/g)) { // 校验位数
return true;
}
return "请输入11位数字";
}
},
{
type: 'confirm',
name: 'ok',
message: '是否确认创建项目',
default: true
}
])
console.log(resp);
down(resp)
}
function down (option) {
const dir = path.join(process.cwd(), "/test"); //这里可以自定义下载的地址
rimraf.sync(dir, {}); //在下载前需要保证路径下没有同名文件
download(
"https://github.com:koajs/koa#master",
// 假设安装koa,可以填自己的项目,
// 可以根据问答内容选择git上项目的版本
// 公司git请在https前加 direct:
dir,
{ clone: true },
function (err) {
console.log(err ? "Error" : "Success", err);
}
);
}
module.exports = (...args) => {
return create(...args).catch(e => {
console.log(e);
})
}
我们将包发布到npm上或者上传到自己的git仓库,再全局安装sudo npm i -g clidemo(也可自己建一个空项目先局部安装),再执行clidemo create app
即可创建属于自己的脚手架工程
了解完基础功能后,我们就可以慢慢完善自己的cli了😎