本篇部落客要介紹了如何使用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
代表了這個cli工具向使用者暴露的指令行指令。我們還是拿command
來舉例子,npm install
聲明了一個叫init的指令,在此處,init等價于installcommand('init')
- alias
是對于目前指令行指令的更短的指令。例如大家都知道,alias
可以簡寫為npm install
。npm i
就是定義的aliasi
- description
是對目前指令行指令的描述,commander會自動的生成目前cli工具的幫助文檔,而該描述就會在description
中展示,如果你的一分鐘體驗項目還在的話,在指令行中輸入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.