天天看點

是時候擁有一個你自己的指令行工具了

本篇部落客要介紹了如何使用commander, inquirer以及chalk從零開始,建立屬于自己的指令行工具。

0. 一分鐘體驗

首先我們先花一分鐘的時間,體驗一下建立自己的指令行cli工具是什麼感覺。

0.1. 建立項目目錄

假如我們的項目名稱叫

hello-cli

,使用如下指令建立項目目錄。

mkdir hello-cli && cd hello-cli           

0.2. 初始化項目

接下裡使用npm-init指令來初始化一個簡單的package.json檔案。

npm init -y           

-y

指令表示接受npm的一切預設參數設定。然後替換package.json為如下代碼。

{
  "name": "hello-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "bin": {
    "hello": "hello"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "chalk": "^2.4.2",
    "commander": "^2.20.0",
    "inquirer": "^6.3.1",
    "shelljs": "^0.8.3"
  }
}           

然後使用

npm install

安裝依賴。

0.3. 建立入口檔案

在項目根目錄下建立名為

hello

的檔案,不需要任何字尾,值得注意的是此時的檔案名就是你的cli工具第一個鍵入的指令,例如

npm install

,那麼

hello

就等價于

npm

。并将代碼替換如下。

#! /usr/bin/env node

const program = require('commander');
const inquirer = require('inquirer');
const chalk = require('chalk');

program
  .command('init')
  .alias('i')
  .description('初始化項目')
  .action(option => {
    // 該對象用于存儲所有與使用者互動的資料
    let config = {
      // 假設我們需要使用者自定義項目名稱
      projectName: null
    };
    // 使用chalk列印美化的版本資訊
    console.log(chalk.default.bold('hello v1.0.0'));

    // 用于存儲所有的互動步驟,例如讓使用者輸入項目名稱就是其中一個步驟
    let promps = [];
    if (config.projectName === null) {
      promps.push({
        type: 'input',
        name: 'projectName',
        message: '請輸入項目名稱',
        validate: input => {
          if (!input) {
            return '項目名稱不能為空';
          }
          // 更新對象中屬性的資料
          config.projectName = input;
          return true;
        }
      });
    }

    // 至此,與使用者的所有互動均已完成,answers是收集到的使用者所填的所有資料
    // 同時,這也是你開始操作的地方,這個cli工具的核心代碼應該從這個地方開始
    inquirer.prompt(promps).then(async (answers) => {
      // do something here
      console.log(answers);
    });
  });

program.parse(process.argv);           

0.4. npm link

那麼問題來了,

在你的項目根目錄下使用

npm link

,然後在你本地上就相當于安裝了名為

hello-cli

這樣的一個全局npm包了。其原理是将你本地的項目在全局的node_modules中做了一個軟連結,拿此項目舉例,全局的

hello

指令已經指向了你的本地目錄。如果你想取消測試項目在全局中的映射,同樣的進入項根目錄,輸入指令

npm unlink

即可。

然後搭配以下指令食用你的第一個cli工具吧。如果報錯提示沒有權限,在指令前加上sudo即可。

hello init
# 或者
# hello i           

1. commander

commander

是一個Node.js環境下的指令行接口解決方案。在上面的一分鐘體驗例子中,我們用到了

command

,

alias

description

action

這四個API。

  • command

    command

    代表了這個cli工具向使用者暴露的指令行指令。我們還是拿

    npm install

    來舉例子,

    command('init')

    聲明了一個叫init的指令,在此處,init等價于install
  • alias

    alias

    是對于目前指令行指令的更短的指令。例如大家都知道,

    npm install

    可以簡寫為

    npm i

    i

    就是定義的alias
  • description

    description

    是對目前指令行指令的描述,commander會自動的生成目前cli工具的幫助文檔,而該描述就會在

    hello -h

    中展示,如果你的一分鐘體驗項目還在的話,在指令行中輸入

    hello -h

    就可以看到自動生成的幫助文檔了
  • action

    action

    是我們注冊我們自己回調函數的地方
  • parse

    parse

    指令則是解析指令行

下面是一分鐘體驗項目中沒有使用的指令,option。還是舉一個例子。如果有用過

hexo

的應該熟悉這個指令。

hexo new post $YOUR_POST_NAME           

沒用過也沒關系,這個指令是用于建立一個可以自定義名字的Markdown的文檔的。大家可能會發現,上面的指令包含了4個單詞,而我們的例子中隻有兩個。那是因為一分鐘項目中沒有使用commander的

option

API。

如果你想在hello項目中實作一樣的指令,那麼隻需要在program中調用該API即可。

.option('-p, --post', 'add post')

,然後就可以通過

option

參數擷取到-p後面,使用者輸入的參數的值。

2. inquirer

大家也發現了,在指令行輸入init指令後,我們需要不停地與指令行進行互動拿到資料,但是在代碼裡并沒有怎麼展現,這是因為我們用了

inquirer

來幫我們做這些事情。

通過inquirer,我們可以實作輸入框,擷取使用者的輸入資料,還可以實作選擇框。舉個例子,用過antd-design-pro應該熟悉建立項目的流程。在指令行中輸入指令

yarn create umi

,在之後的流程中就會出現一個可選擇的list。隻需要将步驟中的代碼替換成如下即可。

promps.push({
    type: 'list',
    name: 'projectName',
    message: '請輸入項目名稱',
    choices: [
      {
        name: 'ant-design-pro',
        value: 'ant-design-pro'
      },
      {
        name: 'dva',
        value: 'dva'
      }
    ]
});           

在項目中,還使用了

validate

來對使用者的輸入資料進行驗證,如果不需要驗證的話,直接把validate整個代碼删除掉就好。

3. chalk

chalk

沒有什麼好介紹的,官網上的文檔已經寫的很詳細了。給大家列一下項目中使用的例子就好。

// 使用預設的字型顔色,加粗字型
console.log(chalk.default.bold('hello v1.0.0'));
// 列印藍色的提示資訊
console.log(chalk.blue('hello v1.0.0'));
// 字元串模闆用法,在同一行中列印不同樣式的資訊
console.log(chalk`{white.bold [1/3]} ` + chalk`{default.bold Clone project into local path...}`);           

4. 最後

如果你厭倦了Node.js寫後端,想用Java的Spring Boot來寫,但是又擔心環境的搭建浪費太多時間。那麼你可以試試

venus-init

,隻需要一行指令便可以快速搭建Java的開發環境。

Happy hacking.