commanderJs編寫命令行工具(cli)


前言:

  最近需要做一個內部的node cli來獨立構建流程,對整個命令行工具實現流程有了大致了解,下面來解釋一下如何實現一個cli,和如何使用  commander 庫。
 

新手誤區:

  在開始實現之前,我知道有  commander 這個node庫,有很多cli使用了它,對它的大致了解就是它可以幫助開發者簡化實現命令流程。  於是最初以為不利用庫要去實現命令行會很麻煩, commander 幫我們解決了各種兼容問題等等。  后來發現並不是的,沒有 commander 我們也可以不用化多大力氣實現命令行, commander 僅僅是一個本身也不太復雜的封裝(源碼也只有1200行)。  我們的第一步還是應該先搞清楚,通過 npm如何實現命令行。
 

一個簡單的cli:

bin:

  package.json 中有一個 bin 字段,指定各個內部命令對應的可執行文件的位置。   在包安裝時,如果是全局安裝,npm 將會把 package.json 里定義的 bin 文件軟連接到全局 node_modules/bin,如果是非全局安裝,會軟鏈接到項目文件夾./node_modules/.bin/。  根據下面代碼的配置,當我們全局安裝此包后,在任意位置運行 cli-test,都會執行全局 node_modules 中的 cli-test 文件。

/*cli-test 的 package.json*/
"bin": {
    "cli-test": "./bin/cli-test"
}

 

如果我們把cli安裝在項目A node_modules中,通過設置項目中 package.json scripts,運行 npm run clinpm 就會在項目的 node_modules/.bin 尋找並運行 cli-test 文件。 

/*項目A package.json*/
"scripts": {
    "cli": "cli-test"
}

 

cli文件:

  下面是 cli-test 文件,第一行必寫,是告訴Unix和Linux系統這個文件中的代碼用node可執行程序去運行它。  后面就做我們要做的事情就行了 。

#!/usr/bin/env node

//do something

 

好了,到這里我們的cli就完成了。  其實有很多三方cli也並沒有用類似 commandernode 庫,如果我們的 cli 足夠簡單,以上這樣就可以了。  下面接着講 commander

 

commander:

現在我們先寫一個簡單的文件來理解(也推薦先自行預覽一下 commander 官方文檔),下面是 bin 文件夾的 cli-test,代碼如下:

 

#!/usr/bin/env node

const program =require('commander');
program
.usage('[option]', '--type required')
.option('--type [typeName]', 'type: dev && build')
.parse(process.argv);

const {type} = program;
if(type == 'dev'){
    console.log('do something', type)
}else if(type == 'build'){
    console.log('do something', type)
}else{
    console.log('params error');
    program.help();
}

 

解釋一下上面的代碼,從查看源碼里發現 require('commander')  會 new一個commander 內部的單例對象並返回,program 已經是一個實例,。  .usage  僅僅描述了參數規則,會在 --help 中打印出來。.option 定義了一個參數名和描述,  parse 會解析命令之中的參數,根據上面定義好的規則執行相關命令。  比如上面的代碼定義了 option 類型的參數 --type,執行 .parse 的時候,parse 根據 process.argv 之中的參數,獲取到 --type,並把參數命和參數值存儲在內部 commander 實例的屬性之中,因此后面的代碼就能從 program 之中取到 type,如果 type 不存在或者不是我們約定的值,最后我們打印參數錯誤,並執行help方法打印了 --help。  如下截圖,我們 node 執行 cli-test,因為沒有約定參數,所以執行了 else 的程序。(因為這里是本地的demo程序,所以直接使用node命令)

 

接着,我們執行正確的命令參數,如下

 

這樣一個簡單的demo就實現了,看起來也挺簡單的,commander 封裝了一些也不算很復雜的功能。 

 

再來一個例子:

新建了兩個文件,要以 bin 命令的執行文件命后面加上 -name,作為子命令文件

 

 

cli-test:

#!/usr/bin/env node

const program =require('commander');

program
.usage('<command> [option]', 'option --type required')
.command('h5', 'to h5')
.command('rn', 'to rn')
.parse(process.argv);

 

cli-test-h5:

#!/usr/bin/env node

const program =require('commander');
program
.option('--type [typeName]', 'type: dev && build')
.parse(process.argv);

const {type} = program;
if(type == 'dev'){
    console.log('do something h5', type)
}else if(type == 'build'){
    console.log('do something h5', type)
}else{
    console.log('params error');
    program.help();
}

 

cli-test-rn:

#!/usr/bin/env node

const program =require('commander');
program
.option('--type [typeName]', 'type: dev && build')
.parse(process.argv);

const {type} = program;
if(type == 'dev'){
    console.log('do something rn', type)
}else if(type == 'build'){
    console.log('do something rn', type)
}else{
    console.log('params error');
    program.help();
}

 

先直接運行3個命令運行程序,看下結果,而后分別解釋一下:

 

node ./bin/cli-test:

定義了.command子命令卻沒有相應執行參數,commander對象會直接打印-help,process.exit退出進程。  

 

node ./bin/cli-test h5 --type dev:

cli-test 通過 command 方法約定子命令名稱和描述,如 h5,當執行 node cli-test h5 --type dev的時候,cli-test 執行到 .command('h5', 'to h5')  ,會在當前 commander 實例內部,new 一個 name h5 的子 commander,存儲在當前父實例的 commands 數組中,當 .parse(process.argv) 執行,獲取到參數中 h5 后,在 commands 里查找是否有 nameh5commander 子實例,如果查找到,啟動一個子進程按照命名規則執行 cli-test-h5 文件並帶入后面的 option 參數這樣 commander 就幫助我們實現了多文件命令划分,我們可以把不同類型的執行代碼放在不同的文件中

 

node ./bin/cli-test rn --type build:

同上

 

小結

bin 文件夾下的這3個 node 文件他們都是 commander 實例,commander 庫只是一個簡單的封裝,幫助定義 多文件命令、執行參數 、簡易文檔,參數驗證等。  以上就是 commander 的大致使用和我對其的理解。   源碼不多,建議可以深入學習一下。

 

最后

  到最后大家結合實現以上所說的 cli commander,一個 commander 實現的命令行工具就能完成了,是不是很簡單!?  

 

注意

  如果執行命令發現報錯為 error: xx(1) not executable. try chmod or run with root,要注意下創建的文件類型。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM