小白入门cli

345 阅读3分钟

什么是cli

cli是command-line interface的缩写,即命令行工具,常用的vue-cli, create-react-app,express-generator 等都是cli工具。

牛刀小试:cli的发布与安装

假设脚手架的名字叫my-cli,在命令行使用的命令是my-cli

怎么让用户通过npm或者yarn全局安装我的工具,在终端执行my-cli呢,答案就在package.jsonbin字段

创建一个my-cli目录,使用cmd进入目录:

mkdir my-cli && cd my-cli

在该目录下创建index.js

//index.js
 console.log('hello')

使用node运行index.js:

img.png

这是node的基本用法,下面自定义命令行输出这段话:

使用npm init 初始化一个package.json,可以配置相关信息,也可以一路回车

img_1.png

目录中生成了一个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来运行文件了:

img_2.png

在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)))