什么是cli
cli是command-line interface的缩写,即命令行工具,常用的vue-cli, create-react-app,express-generator 等都是cli工具。
牛刀小试:cli的发布与安装
假设脚手架的名字叫
my-cli,在命令行使用的命令是my-cli
怎么让用户通过npm或者yarn全局安装我的工具,在终端执行my-cli呢,答案就在package.json的bin字段
创建一个my-cli目录,使用cmd进入目录:
mkdir my-cli && cd my-cli
在该目录下创建index.js
//index.js
console.log('hello')
使用node运行index.js:
这是node的基本用法,下面自定义命令行输出这段话:
使用npm init 初始化一个package.json,可以配置相关信息,也可以一路回车
目录中生成了一个package.json文件,我们在里面添加bin字段,存放可执行文件,我们的可执行文件就是index.js
{
"name": "my-cli",
"version": "1.0.0",
"description": "",
"bin": {
"my-cli": "./index.js"
},
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
此时我们配置了my-cli命令执行index.js,需要在index.js文件头部添加#!/usr/bin/env node, 让系统自己去找node的执行程序
#!/usr/bin/env node
// --这种用法是为了防止操作系统用户没有将node装在默认的/usr/bin路径里。当系统看到这一行的时候,
// 首先会到env设置里查找node的安装路径,再调用对应路径下的解释器程序完成操作。
console.log('this is my-cli');
然后在cmd输入npn linkk或npm install -g将当前项目安装到全局环境,这样就可以直接使用my-cli来运行文件了:
在package.json的scripts字段里添加脚本名:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"mcli":"my-cli"
}
命令行输入npm run mcli,命令行同样输出了index.js里的内容,联想起vue-cli的npm run dev、npm run build
进阶
好奇如何生成项目模板,这块内容就能做到
拷贝文件
将本地的template.js文件,复制到新生成的项目模板中,新生成的项目模板中新建public目录,templare.js通过copyTemplate()方法从template里拷贝到新建的public目录下面:
var fs = require('fs');
var path = require('path');
//复制文件
function copyTemplate ( ) {
//创建目录
fs.mkdir('./public',function(){
from = path.join(__dirname, '../template', 'template.js');
//文件读写
fs.writeFileSync('./public/template.js', fs.readFileSync(from, 'utf-8'))
})
}
用cmd打开任意文件夹输入my-cli,该文件夹下会生成`public\template.js
拷贝文件夹
接收命令行参数
我们可以使用process.argv获取命令行参数,process.argv是一个参数数组,第一项为node.exe的绝对路径,第二项为执行该js的绝对路径,使用process.argv.slice(2)即可获取输入的参数数组:
cdm输入my-cli -l -s
解析命令行指令和参数,commander.js()
// 定义版本和参数选项
program
.version('0.1.0', '-v, --version')
.description('this is my cli')
.option('-i, --init', 'init something')
// 自定义帮助信息
program.on('--help', function(){
console.log(' Examples:');
console.log(' this is an example');
});
//自定义命令
program.command('init')
.description('init something')
.alias('i')
.option('--l','this is init option')
.action((...args)=>{
//复制文件
copyTemplate();
console.log('this is init')
})
//用于解析process.argv
program.parse(process.argv);
实现命令行交互 inquirer.js
在command命令,action回调添加下面的代码啊:
.action(() => {
inquirer.prompt([
{
type:'input',
message:'姓名',
name:'name'
},{
type:'input',
message:'手机号',
name:'phone',
validate:val=>{
if(val.match(/\d{11}/g)){
return true
}
return '请输入11位数字'
}
},{
type:'confirm',
message:'是否参加本次考核?',
name:'assess',
prefix:'前缀'
}
]).then(answers=>{
//获得上面的答案
console.log(answers);
})
})
拉取远程仓库 download-git-repo
const download = require("download-git-repo");
// 第一个git地址,第二个name是git clone下来后的名字...
download(
"https://github.com/yokiyokiyoki/vue-fullpage.git#master",
name,
{ clone: true },
err => {
...
}
);
chalk美化命令行
console.log(chalk.green('考核完成'))//字体绿色
console.log(chalk.blue('你最棒了'))//字体蓝色
console.log(chalk.blue.bgRed('五一放假喽')) //支持设置背景
console.log(chalk.blue(JSON.stringify(answers)))