想想你的團隊會有一些重複性工做嗎?思考一下,CLI 工具也許能夠減小掉許多重複工做,統一合做規範,提高工做效率。node
Node 擁有最爲龐大的生態社區,數十萬的 Package,其中有許多 Package 是專門爲建強大的 CLI 工具打造的。在社區生態的幫助下,你能夠更快速構建更強大的 CLI 工具。同時,在 NPM、Yarn 等 Package 管理工具的幫助下,你也能夠快速的分發的你的 CLI 工具,讓你的用戶更簡單的使用你的 CLI 工具。git
初始化項目github
mkdir cli-tool && cd cli-tool
npm init --yes
複製代碼
建立 src/cli.js
,寫入以下內容:npm
// src/cli.js
module.exports = function cli() {
// 打印命令參數
console.log(process.argv);
};
複製代碼
建立 bin/cli.js
文件,這是 CLI 工具的入口文件,寫入以下內容:json
#!/usr/bin/env node
const cli = require("../src/cli");
cli();
複製代碼
重點:修改 package.json
,寫入 bin
字段,添加 cli
命令數組
{
"name": "cli-tool",
"version": "1.0.0",
"description": "",
"main": "src/cli.js",
"bin": {
"cli": "bin/cli.js"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
複製代碼
在項目根目錄下,運行:bash
npm link
複製代碼
在終端中輸入 cli
命令,便可打印出以下相似內容:app
[
'/Users/xx/.nvm/versions/node/v12.16.2/bin/node',
'/Users/xx/.nvm/versions/node/v12.16.2/bin/cli'
]
複製代碼
至此,一個簡單的 Node CLI 工具就完成了。工具
NPM 實現了將 Package 中的可執行文件添加全局 PATH 中的能力,當在 package.json
文件中添加 bin
字段時,NPM 會將 bin
聲明的文件連接(軟連接)到 bin
目錄中(全局可用),或者 ./node_modules/bin/
(本地可用)。動畫
以下面的 bin
建立 /usr/local/bin/myapp
到 cli.js
的軟連接:
{ "bin" : { "myapp" : "./cli.js" } }
複製代碼
同時,咱們要在 bin
聲明的文件的開頭添加 #!/usr/bin/env node
聲明,確保系統會用 Node 執行此文件。
npm link
命令會建立當前 Package 到 Gloabl 的軟連接,使當前 Package 在全局可用,相似虛擬的 npm i --global packae
命令,在本地調試時十分有用。
CLI 工具的基本能力就是要解析用戶輸入的 CLI 命令與參數,實現相關功能。Node 的 process.argv
數組包含了 Node
進程被啓動時傳入的命令行參數,經過解析 process.argv
數組便可,社區中相關的 Package 也比較多,如:yargs,minimist 等。
這裏推薦使用 [commander](https://github.com/tj/commander.js)
構建你的 CLI 工具,commander 是一個較爲完善的 Node CLI 解決方案,擁有解析輸入參數、關聯處理邏輯、輸出命令提示等功能。只有當 commander 的功能沒法知足你的需求時,才建議你嘗試本身處理命令參數解析。
在某些狀況下,CLI 工具可能須要使用交互式輸入,如輸入密碼時,這種狀況不適合直接經過參數輸入。簡單的輸入時,能夠直接 Node 的 readline
模塊:
const readline = require("readline");
const question = ["請輸入您的姓名", "請輸入您的年齡"];
const result = [];
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: `?${question[0]} `,
});
rl.prompt();
rl.on("line", (line) => {
result.push(line.trim());
const max = result.length;
if (max === question.length) {
rl.close();
}
rl.setPrompt(`?${question[max]} `);
rl.prompt();
}).on("close", () => {
console.log(`謝謝參與問答 *** 姓名: ${result[0]} 年齡: ${result[1]}`);
process.exit(0);
});
複製代碼
當須要比較複雜的交互時,如列表選擇時,就須要使用社區中的 Package 了。這裏推薦 enquirer,功能較爲強大,以下:
最後,你能夠經過 NPM 將你的 Node CLI 工具快速分發出去:
# 登錄 npm
npm adduser
# 打 Tag
npm tag v1.0.0
# 發佈
npm publish
複製代碼