完成一个初步的CLI

197 阅读3分钟

一、什么是CLI

cli相当于一个命令行界面,我们常用的npm install 、npm run xxx 都属于CLI命令

二、创建一个CLI

1、初始化

创建个文件夹,执行npm init 初始化项目,package.json内容如此

{
  "name": "ycli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

2、编辑package.json文件

{
  "name": "ycli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
//region 新增
  "bin": {
    "study-test": "index.js"
  },
//endregion
  "author": "",
  "license": "ISC"
}

可以看到我们新增了一个bin,其含义是给我们的cli一个命名,并且指明入口文件为index.js

3、创建入口文件

#! /usr/bin/env node
console.log('进来了')

可以看到我们的入口文件上有一行独特的代码 #! /usr/bin/env node,它是一个Shell脚本规则,其含义是指明这个文件的运行环境为node, /usr/bin/env是我们的本地的环境变量,这个是为了告诉我们的系统从哪里去找node,感兴趣的同学可以看一下www.ruanyifeng.com/blog/2016/1…

4、运行CLI

我们平时使用cli时一般有两种方式,一种是将CLI下载到本地,也就是npm instll global XXX ,还有一种就是npx,两种的区别就是npx不用将CLI包下载到本地,它是一种去引用npm云端CLI的方法,由npm提供,因为我们的包还没有上传到npm的云端,所以npx肯定是不适用了,但是没有上传的云端也不涉及到npm install下载这个问题,我们可以使用npm link,这个命令做的事情的结果类似于npm install global XXX,可以把我们写的库和npm全局建立一个软连接,这样我们运行我们声明的cli命令就可以找到我们的包

可以看到有了进来了的字样,证明我们的cli执行成功了。

🎉撒花,这样我们就完成了一个最简单的CLI

三、处理命令

在我们使用cli的时候往往都是伴随值命令的,例如 vue create app,现在我们已经知道了如何去执行我们的代码,现在我们要学习根据用户输入去执行不同的代码,首先,先去获取用户的输入命令是什么,目前有一个命令行解决方案(库)commander.js

这里简单的说明一下commander的使用,

const { program } = require('commander')
program
// 注册命令
  .command('create <template>')
  .description('create a new project')
// 注册选项
  .option('-v, --vue', 'vue templete')
  .option('-r, --react', 'react templete')
  .option('-v2, --vue2', 'vue2 templete')
  .option('-v3, --vue3', 'vue3 templete')
  .action((projectName, options) => {
    console.log(projectName, options)
  })
program.version('1.0.0', '-v, --version').parse()

尝试一下

study-test create app -v 
app { vue: true }

四、处理交互行为

有的时候我们可能需要在命令行工具中融入一些交互行为,例如选择是否使用ts等,我们可以引入包inquirer来处理这一行为,简单的上手文档juejin.cn/post/722137…

const inquirer = require('inquirer')
// 创建一个问题模块
const prompt = inquirer.createPromptModule()
// 创建问题
const questions = [{
  type: 'input',
  name: 'name',
  message: 'what is your name?',
  default: 'yuexingyu'
},
{
  type: 'password',
  name: 'password',
  message: 'this is password'
},{
  type: 'confirm',
  name: 'confirm',
  message: 'Do you like BbQ?',
  default: true
},{
  type: 'list',
  name: 'list',
  message: 'what is you favourite programming language?',
  choices: ['JS', 'node', 'Java'],
  default: 'JS'
},{
  type: 'checkbox',
  name: 'checkbox',
  message: 'this is checkbox',
  choices: [
    { name: 'HTML', checked: true },
    { name: 'CSS', checked: true },
    { name: 'JavaScript', checked: true },
    { name: 'Node.js' },
    { name: 'React' },
    { name: 'Vue' }
  ]
}]
// 进行提问
prompt(questions).then(answer => {
      console.log('回答', answer)
    })

试一下

study-test create app

what is your name? yuexingyu
? this is password [hidden]
? Do you like BbQ? Yes
? what is you favourite programming language? node
? this is checkbox Node.js, React
回答 {
  name: 'yuexingyu',
  password: '123456',
  confirm: true,
  list: 'node',
  checkbox: [ 'Node.js', 'React' ]
}