Node.js編寫(xiě)CLI的實(shí)例詳解
Why Node.js?
常用的用來(lái)編寫(xiě)CLI的語(yǔ)言有 python, ruby, perl, Node.js等等。 為什么選取Node.js作為CLI的語(yǔ)言編寫(xiě)工具呢?有三個(gè)理由:
- 對(duì)Javascript語(yǔ)言更加熟悉
- npm 完善的生態(tài)系統(tǒng)
- npm OS無(wú)關(guān)的包管理機(jī)制
主要原因還是歸咎于npm 完善的生態(tài),目前npm官方有47.5萬(wàn)個(gè)三方包可供使用,你可以很方便的使用一些已經(jīng)編寫(xiě)的很不錯(cuò)的輪子去幫你快速開(kāi)發(fā)。另一方面,你不需要考慮跨平臺(tái)的安裝問(wèn)題,比如OSX上的homebrew、Debian的aptitude、CentOS 上的yum。如果使用shell或者其它語(yǔ)言來(lái)編寫(xiě)CLI,需要針對(duì)各個(gè)主流OS來(lái)做兼容并且發(fā)布到不同的平臺(tái)。
看個(gè)demo

注: 此處的Logo使用的是figlet這個(gè)npm包來(lái)幫助生成
npm關(guān)聯(lián)CLI的基本原理
如何讓Node.js編寫(xiě)的包可執(zhí)行?其實(shí)很簡(jiǎn)單,只需要在package.json里面增加一個(gè)bin字段。模塊發(fā)布到npm上后,開(kāi)發(fā)者安裝這個(gè)包的時(shí)候會(huì)檢查是否有bin字段,如果有bin字段則會(huì)使用軟鏈接的方式創(chuàng)建可以全局使用的命令。
如果模塊采用全局安裝的方式,對(duì)于類unix系統(tǒng),會(huì)在/usr/local/bin目錄創(chuàng)建軟鏈接,對(duì)于windows系統(tǒng),在C:\Users\username\AppData\Roaming\npm目錄創(chuàng)建軟鏈接。
如果模塊采用局部安裝的方式,則會(huì)在項(xiàng)目?jī)?nèi)的./node_modules/.bin目錄創(chuàng)建軟鏈接。
配置好的package.json如下:
…
"description": "A command line tool aims to improve front-end engineer workflow.",
"main": "lib/index.js",
"bin" : {
"feflow" : "./bin/feflow"
}
…
CLI基本命令設(shè)計(jì)
$ feflow --help A command line tool aims to improve front-end engineer workflow Usage: feflow [options] [command] Commands: init Choose a scaffold to initialize project. scan --receiver Scan a group and mail to receiver install <plugin> Install a plugin or a yeoman generator. Options: --version, -[vV] Print version and exit successful --help, Print this help and exit successf
Feflow的技術(shù)架構(gòu)
Feflow總體分為3個(gè)模塊,包括parser命令行參數(shù)解析、核心命令以及插件機(jī)制。設(shè)計(jì)插件主要是為了保持整體功能的穩(wěn)定,避免頻繁升級(jí);同時(shí)開(kāi)放能力,支持開(kāi)發(fā)者接入,完善整體的生態(tài)。

掃描器的實(shí)現(xiàn)
在一個(gè)工程項(xiàng)目中,有各種各樣的規(guī)范,比如項(xiàng)目命名規(guī)范、描述規(guī)范、目錄結(jié)構(gòu)規(guī)范、README.md規(guī)范,是否增加基本監(jiān)控等等。編寫(xiě)掃描器scanner,對(duì)某個(gè)Group里面的所有業(yè)務(wù)項(xiàng)目進(jìn)行掃描,將不符合規(guī)范的倉(cāng)庫(kù)和不符合規(guī)范的地方列舉出來(lái),并且撈出責(zé)任人。最后通過(guò)郵件及定時(shí)任務(wù)發(fā)送給相關(guān)同學(xué),并且敦促修改。掃描器流程圖如下:

首先,需要一個(gè)任務(wù)隊(duì)列,隊(duì)列里面存放不同的掃描任務(wù)。每個(gè)掃描任務(wù)依賴相關(guān)的文件信息或者Commit信息,這個(gè)時(shí)候需要調(diào)用Git code提供的三方API進(jìn)行文件信息拉取。之后,需要編寫(xiě)一個(gè)規(guī)則引擎,這個(gè)規(guī)則引擎里面有多個(gè)規(guī)范相關(guān)的檢查工具,解析完成后會(huì)將結(jié)果生成HTML格式的字符串。最后調(diào)用郵件服務(wù)和定時(shí)任務(wù)服務(wù)去通知相關(guān)開(kāi)發(fā)者。
插件機(jī)制設(shè)計(jì)
$ feflow install <plugin> # 安裝一個(gè)插件, --force則會(huì)強(qiáng)制安裝 $ feflow remove <plugin> # 卸載一個(gè)插件 $ feflow list # 列舉出所有插件信息 $ feflow list <plugin> # 列舉某個(gè)插件信息
插件機(jī)制實(shí)現(xiàn)
插件機(jī)制的實(shí)現(xiàn)包括兩個(gè)部分:插件注冊(cè)機(jī)制和插件發(fā)現(xiàn)機(jī)制。feflow要求插件必須以feflow-plugin-開(kāi)頭或者 generator-開(kāi)頭,generator作為一種特殊的插件,插件代碼以npm包的形式存儲(chǔ)和管理。運(yùn)行feflow install plugin命令時(shí),會(huì)通過(guò)npm 的 regsitry檢查是否存在插件,如果存在,會(huì)檢查當(dāng)前插件是否是最新版本。如果不是最新版本,則提示用戶是否需要更新。然后將插件下載到Home目錄下的.feflow目錄(Windows系統(tǒng)為"C:\Users\username\.feflow" 目錄)下的node_modules里面,并且寫(xiě)入到配置文件里面。
本地模塊注冊(cè)機(jī)制

本地模塊發(fā)現(xiàn)機(jī)制

npm 的 registry服務(wù)
- npm的查詢服務(wù)網(wǎng)址:http://registry.npmjs.org/
- registry網(wǎng)址后面跟上模塊名、版本好可以查詢模塊詳細(xì)信息,包括最新版本,以此來(lái)判斷模塊是否需要更新。比如:React的最新版本可以通過(guò)http://registry.npmjs.org/react/latest 來(lái)獲得
- 返回的JSON對(duì)象里面有個(gè)dist.tarball屬性,是某個(gè)版本的壓縮包地址
常用三方包分享
- osenv 方便的獲取不同系統(tǒng)的環(huán)境和目錄配置
- figlet 命令行炫酷的Logo生成器
- meow 命令行幫助命令封裝
- inquire 強(qiáng)大的用戶交互
- chalk 讓命令行的output帶有顏色
- easytable 表格信息展示,用于升級(jí)包的提示
- minimlist 用戶輸入的參數(shù)解析
- shelljs Node.js執(zhí)行shell命令
- clui 進(jìn)度條
遇到的問(wèn)題
1,windows下用戶未設(shè)置HOME環(huán)境變量導(dǎo)致報(bào)錯(cuò)
解決辦法: 由于windows下HOME環(huán)境變量并非默認(rèn)存在,因此不能直接使用。判斷process.platform === ‘win32',優(yōu)先使用HOME變量,否則使用USERPROFILE變量;建議使用osenv這個(gè)包。
2,OSX平臺(tái)運(yùn)行feflow報(bào)錯(cuò): env: node\r: No such file or directory
解決辦法: 由于類unix系統(tǒng)的換行符號(hào)為\n,而windows系統(tǒng)為\n\r。修復(fù)換行問(wèn)題??梢栽诠こ谈夸浵录?gitattributes文件,設(shè)置* text eol=lf,這樣git提交時(shí)就不會(huì)講LF轉(zhuǎn)換成CRLF
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Node.js中的EventEmitter類使用小結(jié)
EventEmitter 是 Node.js 中的一個(gè)核心模塊,它提供了一種實(shí)現(xiàn)事件驅(qū)動(dòng)編程的機(jī)制,它是一個(gè)基于觀察者模式的類,用于在應(yīng)用程序中處理事件和觸發(fā)事件,這篇文章主要介紹了Node.js中的EventEmitter類介紹,需要的朋友可以參考下2023-12-12
node.js使用http模塊創(chuàng)建服務(wù)器和客戶端完整示例
這篇文章主要介紹了node.js使用http模塊創(chuàng)建服務(wù)器和客戶端,結(jié)合完整示例形式分析了node.js基于http模塊實(shí)現(xiàn)客戶端與服務(wù)器端交互的相關(guān)操作技巧,需要的朋友可以參考下2020-02-02
Node.js web 應(yīng)用如何封裝到Docker容器中
這篇文章主要介紹了Node.js web 應(yīng)用如何封裝到Docker容器中,幫助大家更好的學(xué)習(xí)node.js和使用docker容器,感興趣的朋友可以了解下2020-09-09
使用Node.js的async和await進(jìn)行異步編程
使用異步編程可以提高Node.js應(yīng)用程序的性能,而async和await是Node.js中實(shí)現(xiàn)異步編程的一種簡(jiǎn)單且易于使用的方式,可以幫助開(kāi)發(fā)者避免回調(diào)地獄和處理異步操作時(shí)的錯(cuò)誤2023-05-05
Node.js事件循環(huán)(Event Loop)的使用
事件循環(huán)是其非阻塞I/O和高并發(fā)能力的核心機(jī)制,本文主要介紹了Node.js事件循環(huán)(Event Loop)的使用,具有一定的參考價(jià)值,感興趣的可以了解一下2024-05-05
nodejs socket實(shí)現(xiàn)的服務(wù)端和客戶端功能示例
這篇文章主要介紹了nodejs socket實(shí)現(xiàn)的服務(wù)端和客戶端功能,結(jié)合具體實(shí)例形式分析了nodejs基于socket通信實(shí)現(xiàn)的服務(wù)端與客戶端功能相關(guān)操作技巧,需要的朋友可以參考下2017-06-06

