一. 创建目录 & 文件 & package
-
整体目录 结构如下
my-cli/ ├── bin/ │ └── cli.js # 脚手架入口 ├── templates/ # 模板目录 │ └── project/ # 项目模板 │ ├── _package.json │ └── src/ │ └── index.js ├── lib/ │ ├── create.js # 项目创建逻辑 │ └── utils.js # 工具函数 └── package.json
第一: 在 my-cli
项目目录中,创建bin
目录以及cli.js
-
cli.js
文件中#!/usr/bin/env node console.log(process.argv);
其中
#!/usr/bin/env node
这行代码的作用就是告诉系统(不同系统 Unix/Linux/macOS),让用户无需显式输入node script.js
,只需./script.js
即可运行另外
process.argv
来获取命令中的参数,(process
是node中一个全局变量,提供了有关当前Node.js
进程的信息并对其进行控制)
第二: 在 my-cli
项目目录中,使用 npm init
生成 package.json
文件
{
"name": "mycli",
"version": "1.0.0",
"main": "index.js",
"bin": {
"mycli": "./bin/cli.js"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
}
第三: 在当前项目目录中,使用 npm link
(如果你是在本地开发,需要将包链接到全局)
第四: 在命令行中执行代码 mycli
,可以看到cli.js
中console.log
信息
二. 命令行库(轻松定义命令、选项、参数以及处理用户输入) commander
- 安装
commander
依赖
// 安装依赖
npm install commander
- 通过
command
配置命令
const program = require("commander");
program
.command('create <project> [other...]')
.alias('c')
.description('创建项目')
.action((project, other) => {
// 命令行执行逻辑代码
// 这边是 project
console.log('创建项目', project, other);
})
.command()
的第一个参数为命令名称。命令参数可以跟在名称后面,也可以用.argument()
单独指定。参数可为必选的(尖括号表示)、可选的(方括号表示)或变长参数(点号表示,如果使用,只能是最后一个参数)。
.argument()
表示 参数定义,跟.command()
的一样
.alias()
表示别名
.description()
表示 当前命令描述
.action()
表示 回调函数
.option()
表示 定义选项,参数:
短选项名称(-后面接单个字符)和一个长选项名称(--后面接一个或多个单词),使用逗号、空格或|
分隔。并且短和长选项名称,后面也可以带上参数
可为必选的(尖括号表示)、可选的(方括号表示)或变长参数(点号表示,如果使用,只能是最后一个参数)
program
.command('create <project> [other...]')
.alias('c')
.description('创建项目')
.option('--first', 'display just the first substring')
.action((project, other) => {
// 命令行执行逻辑代码
// 这边是 project
console.log('创建项目', project, other);
})
program
.version('0.1.0')
.argument('<username>', 'user to login')
.argument('[password]', 'password for user, if required', 'no password given')
.action((username, password) => {
console.log('username:', username);
console.log('password:', password);
});
program.command('split')
.description('Split a string into substrings and display as an array')
.argument('<string>', 'string to split')
.option('--first <char>', 'display just the first substring')
.option('-s, --separator <char>', 'separator character', ',')
.action((str, options) => {
console.log('string:', str, 'options:', options);
const limit = options.first ? 1 : undefined;
console.log(str.split(options.separator, limit));
});
执行--> mycli c CC 123 或者 mycli create CC 123
打印--> 创建项目 CC [ '123' ]
执行--> mycli split aaa --first ceshi
打印--> string: aaa options: { separator: ',', first: 'ceshi' }
三. 命令行问答式交互库 inquirer
- 安装
inquirer
// 安装
npm install @inquirer/prompts
通过 inquirer.prompt()
来实现。prompt
函数接收一个数组,数组的每一项都是一个询问项,下面是常用的配置项。
-
type
:提问的类型,常用的有类型 描述 示例 input
文本输入 { type: 'input', name: 'name', message: '姓名:' }
number
数字输入 { type: 'number', name: 'age', message: '年龄:' }
confirm
是/否选择 { type: 'confirm', name: 'agree', message: '同意协议?' }
list
单选列表 { type: 'list', name: 'color', choices: ['红', '绿', '蓝'] }
checkbox
多选框 { type: 'checkbox', name: 'tools', choices: ['Git', 'Docker', 'K8s'] }
password
密码输入 { type: 'password', name: 'pwd', mask: '*' }
select
下拉框 { type: 'select', name: 'xiala', mask: '*' }
-
name
:存储当前问题答案的变量; -
message
:问题的描述; -
default
:默认值; -
choices
:列表选项,在某些type
下可用; -
validate
:对用户的答案进行校验; -
filter
:对用户的答案进行过滤处理,返回处理后的值。 -
等等
例子:
const inquirer = require('inquirer');
inquirer.prompt([
{
type: 'input',
name: 'username',
message: '用户名:',
validate: input => input.trim() !== '' || '不能为空'
},
{
type: 'password',
name: 'password',
mask: '•',
message: '密码:',
validate: input => input.length >= 6 || '至少6个字符'
},
{
type: 'list',
name: 'role',
message: '角色:',
choices: ['用户', '管理员', '开发者']
},
{
type: 'checkbox',
name: 'skills',
message: '选择技能:',
choices: ['JavaScript', 'Python', 'Java', 'Go']
}
]).then(answers => {
console.log('\n注册信息:');
console.log('用户名:', answers.username);
console.log('角色:', answers.role);
console.log('技能:', answers.skills.join(', '));
});
三. 下载远程项目代码库 download-git-repo
- 安装
download-git-repo
npm install download-git-repo
download('direct:'+config.framworkPath[answer.framwork], project, { clone: true },function (err) {console.log(err ? 'Error' : 'Success') })
四. 命令行loading库ora
npm install ora@5
const ora = require("ora");
const spinner = ora().start('downloading');
setTimeOut(()=>{
spinner.succeed("download success");
// spinner.fail("download fail");
})
五. 命令行样式渲染库 chalk
npm install chalk@4
const chalk = require("chalk");
console.log( chalk.blue('cd project') );
console.log( chalk.green.bold('npm install') );
console.log( chalk.rgb(123, 45, 67)('npm run dev') );