我們在前端開發中會經常用到命令行工具,比如@babel/cli、vue-cli、create-react-app 等等。那么如何創建一個npm 命令行工具呢?其實很簡單的,僅需要幾步即可。
創建
1 初始化npm項目
npm init
package name: (cli) gogocode-cli
version: (1.0.0)
description: my-first-cli
entry point: (index.js)
keywords: npm cli
author: super man
2 配置bin字段
npm init 后會生成一個package.json文件,在該文件中添加一個bin字段,bin字段的key就是你的命令(gogocode),value指向相對於package.json的路徑(index.js),不同的key對應不同的命令。關於 bin 字段更多信息請參考文檔。
{
"name": "gogocode-cli",
"version": "1.0.0",
"description": "my-first-cli",
"bin": {
"gogocode": "index.js"
}
}
3 創建index.js文件
在項目根目錄創建index.js文件。下面是index.js文件內容:使用console.log() 函數來輸出命令行返回信息。
#!/usr/bin/env node
console.log('Hello, world!');
注意:第一行一定要添加腳本來指定運行環境(#!/usr/bin/env node)
4 打包發布
4.1 發布
- 在項目根目錄執行npm pulish 命令。按照系統提示操作,即可將你的命令行工具發布到 npmjs 平台。期間需要注冊npm賬號,可自行百度。
npm publish
- 打包完成之后,就能在npmjs官網看到你發布的npm包了。
4.2 驗證
- 全局安裝 npm 包
npm install gogocode-cli -g
- 執行命令
gogocode
- 正確輸出 “Hello,World!” 😊
進階&工具
上面只是把npm命令行工具從准備到發布簡單跑通,如果需要構建復雜的npm命令行應用還需要借助一些輔助開發包。下面介紹兩個比較常用npm包: commander 和 terminal-kit
Commander
-
commander用於組織命令行指令(command)和參數(option),它主要負責對命令行的輸入信息進行處理。
- command 可以理解為“指令”用於定義一個代碼邏輯。一般指的是命令行工具第一個空格和第二個空格之間的文本。比如: npm init,其中init就是一個command。一個命令行工具可以支持多個指令輸入。
- option 可以理解為“指令”的函數入參。以 “-” 或者 “--” 開頭,比如:ls -a,其中-a就是一個參數,代表列出全部文件。注意:“-” 為 “--”的簡寫形式。
-
下面以我們最近開發的一個命令行工具 gogocode-cli 為例,為大家具體講解下 commander 如何使用。
- 首先我們看下入口文件index.js的代碼:
#!/usr/bin/env node
const program = require('commander');
const term = require('terminal-kit').terminal;
const pkg = require('./package.json');
//插件加載及執行邏輯
const transform = require('./transform');
//初始化插件項目邏輯
const init = require('./commands/init');
// 配置command
program
.command(`init`)
.description('初始化一個插件sample項目')
.action((options) => {
init(options);
});
// 配置options
program.option('-t, --transform <package name or path>', '插件路徑或者npm包名稱,支持多個插件,逗號分隔')
.option('-o, --out <path>', '輸出文件路徑')
.option('-s, --src <path>', '需要轉換的源文件路徑')
.action((options) => {
return transform(options);
});
// 配置 cli 信息,版本、cli說明等
program
.version(pkg.version)
.description(term.blue('GoGoCode 代碼轉換從未如此簡單 https://gogocode.io'));
console.log();
// 接管命令行輸入,參數處理
program.parse(process.argv);
- 上面的代碼我們可以看出:gogocode-cli 對外支持 init 指令(command) 和 -t,-o,-s 等參數(option)定義,具體定義如下:
參數|指令 | 縮寫 | 參數說明 | 類型 |
---|---|---|---|
init | init | 初始化一個插件sample項目 | command |
--src | -s | 需要轉換的源文件路徑 | option |
--transform=FILE/npm package | -t | 插件路徑或者npm包名稱 | option |
--out | -o | 輸出文件路徑 | option |
- 我們執行一下 index.js:
node ./index.js
結果如下:
我們可以看到 commander 自動幫我們處理指令和參數顯示及邏輯拆分問題,同時自動添加 -V,-h 兩個option。可以說非常方便。
terminal-kit
terminal-kit 是一個功能強大的命令行輸出工具,支持文本樣式、table、menu、進度條等多種交互形式。下面簡單介紹一下幾個常用功能。
- 字體顏色,輸出藍色文本
const term = require('terminal-kit').terminal;
term.blue('GoGoCode 代碼轉換從未如此簡單 https://gogocode.io');
- table表格輸出
const term = require('terminal-kit').terminal;
term.table([
['header #1', 'header #2', 'header #3'],
['row #1', 'a much bigger cell, a much bigger cell, a much bigger cell... ', 'cell']
], {
hasBorder: false,
contentHasMarkup: true,
textAttr: { bgColor: 'default' },
firstCellTextAttr: { bgColor: 'blue' },
firstRowTextAttr: { bgColor: 'yellow' },
firstColumnTextAttr: { bgColor: 'red' },
checkerEvenCellTextAttr: { bgColor: 'gray' },
width: 60,
fit: true // Activate all expand/shrink + wordWrap
}
);
- Yes or No 詢問
const term = require('terminal-kit').terminal;
term('Do you like gogocode? [Y|n]\n');
term.yesOrNo({ yes: ['y', 'ENTER'], no: ['n'] }, function (error, result) {
if (result) {
term.green("'Yes' detected! Good bye!\n");
process.exit();
}
else {
term.red("'No' detected, are you sure?\n");
}
});
調試
命令行工具開發過程中該如何進行Debug呢?我們可以這樣操作。
- 將vscode(最新版本)內置終端(terminal)切換到 JavaScript Debug Terminal
- 使用vscode內置斷點功能,打斷點。
- JavaScript Debug Terminal 中執行 node ./index.js 即可debug
gogocode
以上npm命令行開發經驗都是小編在開發 gogocode-cli 過程中總結而來。gogocode-cli 是 gogocode 的命令行工具。那 gogocode 是什么東東呢?引用一下官方介紹:
GoGoCode是一個操作AST的工具,可以降低使用AST的門檻,幫助開發者從繁瑣的AST操作中解放出來,更專注於代碼分析轉換邏輯的開發。簡單的替換甚至不用學習AST,而初步學習了AST節點結構(可參考AST查看器)后就可以完成更復雜的分析轉換。
gogocode的官方文檔 gogocode.io/zh/docs/spe…
gogocode可以說是一個上手快、使用爽的代碼轉換工具。
gogocode轉換插件
既然gogocode這么好用,那么我們如何使用gogocode來編寫轉換插件呢?下面為大家講解下吧:
插件初始化
- 首先需要安裝gogocode-cli
npm install gogocode-cli -g
- 之后執行 “gogocode init” 來初始化一個插件項目
gogocode init
插件項目結構
gogocode init 初始化后的插件目錄,是一個標准的npm項目。項目的主入口配置在package.json的main節點。
上圖截圖我們可以看到,插件項目轉換邏輯入口為transform.js,具體定義如下:
/**
* 轉換入口導出一個函數,按照如下函數簽名
* @param {*} fileInfo 包含 source 和 path 屬性。source為待轉換文本,path為路徑
* @param {*} api 包含 gogocode 作為轉換工具
* @param {*} options 其他 option 由此傳入
* @returns {string} 返回轉換后的代碼
*/
module.exports = function(fileInfo, api, options) {
const sourceCode = fileInfo.source;
const $ = api.gogocode;
return $(sourceCode)
.replace('const a = $_$', 'const a = 2')
.generate();
};
我們的轉換邏輯需要定義在上面的函數中
轉換邏輯執行
gogocode-cli 執行 js文件
轉換邏輯可以以js文件的形式執行,下面是具體命令:
gogocode -s ./test/input.vue -t ./transform.js -o out.vue
其中,gogocode-cli 命令行參數定義可以參考上面 commander 章節中gogocode-cli的參數定義。
gogocode-cli 執行 npm包
如果想把自己寫好的插件分享給大家,可以直接把這個項目打包成npm包。
gogocode-cli同時也支持運行npm轉換邏輯的功能。
例如我們發布了一個“vue2-to-3”的npm插件。可以執行下面命令,來運行npm包里面的轉換邏輯。
gogocode -s ./test/input.vue -t ./vue2-to-3 -o out.vue
GoGoCode 相關鏈接
GoGoCode的Github倉庫(新項目求star _)
https://github.com/thx/gogocode
GoGoCode的官網
https://gogocode.io/
可以來 playground 快速體驗一下
https://play.gogocode.io/
阿里媽媽出的新工具,給批量修改項目代碼減輕了痛苦
「GoGoCode 實戰」一口氣學會 30 個 AST 代碼替換小訣竅
0成本上手AST,用GoGoCode解決Vue2遷移Vue3難題
GoGoCode協助清理代碼中的「垃圾」