自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解NodeJS和命令行程序

開發(fā) 開發(fā)工具
本文簡述了命令行的意義和優(yōu)勢,介紹了解釋型命令行的運(yùn)行機(jī)制,同時(shí)介紹了幾個(gè)NodeJS相關(guān)的命令行工具,推薦了幾款撰寫命令行程序常用的包,最后,概述了發(fā)布包和使用scope的發(fā)布情況。

源起

植根于Unix系統(tǒng)環(huán)境下的程序,很多都把貫徹Unix系統(tǒng)設(shè)計(jì)的哲學(xué)作為一種追求。Unix系統(tǒng)管道機(jī)制的發(fā)明者Douglas McIlroy把Unix哲學(xué)總結(jié)為三點(diǎn):

  • 專注做一件事,并做到NO.1。
  • 程序協(xié)同工作。
  • 面向通用接口,如文本數(shù)據(jù)流。

隨著Unix/Linux系統(tǒng)在服務(wù)器上影響力越發(fā)強(qiáng)大,以及各種跨平臺(tái)解決方案的發(fā)展,這種哲學(xué)也被帶到了各種平臺(tái)上。若干年前,筆者第一次接觸NodeJS和其包管理解決方案NPM時(shí)候,就感覺到其官方倡導(dǎo)的風(fēng)格,和Unix系統(tǒng)哲學(xué)非常契合。近年來,隨著NodeJS在服務(wù)端以及前端構(gòu)建領(lǐng)域上的不斷開拓,NodeJS的這種思想也正快速的滲透到這些領(lǐng)域。

其實(shí),NodeJS的本身,也是開發(fā)命令行程序的一個(gè)重要利器。本文就將介紹幾個(gè)常用的NodeJS相關(guān)命令行程序,之后介紹幾個(gè)開發(fā)命令行中常用的組件,最后介紹發(fā)布npm包以及帶scope的包的發(fā)布方法。

[[262554]]

命令行是如何工作的

命令行,可以簡單定義為是一種基于文本流的用戶交互接口和交互方式。命令行程序常常通過命令行參數(shù)的傳遞來得到不同的運(yùn)行方式。而由于一切命令的下達(dá),都是基于文本的,所以也為元編程,提供了便利。

命令行程序可以是編譯執(zhí)行的,也可以是解釋執(zhí)行的。對(duì)于編譯后的命令行程序,將直接以機(jī)器碼執(zhí)行。而對(duì)于大多數(shù)的解釋型的命令行程序,運(yùn)行往往需要借助命令行解釋程序。

這篇文章中提到的命令行程序特指需要解釋程序的命令行程序。

可以充當(dāng)命令行解釋程序的,其實(shí)包含了大家聽說過的常見的解釋器,比如bash、zsh、perl、python、ruby、tcl等等,當(dāng)然還有NodeJS。

打開一個(gè)命令行程序,比較標(biāo)準(zhǔn)的寫法是在第一行寫明解釋程序的路徑,如:

  1. #!/usr/local/opt/python/bin/python3.6 

這里 #! 稱為shebang,一般位于文件的最開頭。在Unix系統(tǒng)中,#!所在行后面的部分將被視為解釋器指令。同時(shí)會(huì)把文件所在路徑作為參數(shù)附在解釋器后面。上例中,如果文件是/usr/local/bin/pip,則直接運(yùn)行/usr/local/bin/pip的效果,等同于/usr/local/opt/python/bin/python3.6 /usr/local/bin/pip。

這樣做,使得用戶無需關(guān)心解釋程序,無需關(guān)心代碼編寫的語言,直接運(yùn)行對(duì)應(yīng)的命令行程序本身就好了。這也是shebang存在的意義。不過,由于系統(tǒng)設(shè)定的原因,使用windows的同學(xué)可能無法享受這種便利,一般還需手動(dòng)指定解釋程序的路徑。但是,他們可以雙擊運(yùn)行:-)。

可以試著用文本編輯工具打開一個(gè)NodeJS寫成的腳本如:webpack,會(huì)發(fā)現(xiàn)其第一行是#!/usr/bin/env node。這句話并不是直接的NodeJS的解析程序。這里, /usr/bin/env是一個(gè)程序,目的是從系統(tǒng)的PATH中尋找對(duì)應(yīng)名字的解釋程序的地址。此時(shí),解釋程序可以被安裝在各種路徑,只要在系統(tǒng)PATH中注冊(cè)過,就可以找到了。

可能大家遇到過這種問題,在運(yùn)行某些NodeJS程序會(huì)出現(xiàn)報(bào)錯(cuò):

  1. /usr/bin/env: node: No such file or directory 

此時(shí)可以從系統(tǒng)PATH中是否有node這個(gè)文件路徑、某些版本的NodeJS是否名為node等方向來排查問題。

NodeJS相關(guān):好用的命令行工具

在NodeJS目前已經(jīng)成為前端工作流的主力語言的情況下, babel和webpack基本已經(jīng)成為前端開發(fā)、測試、發(fā)布上的重要工具。同時(shí)圍繞babel和webpack有一系列周邊的工具包和插件協(xié)助開發(fā)者完成日常開發(fā)的方方面面。

同時(shí),目前最為流行的前端框架Angular、react、vue(以首字母為序),各自有自帶的腳手架和開發(fā)輔助工具。如ng-cli、create-react-app和vue-cli等等。更有Poi1這樣的通吃React和Vue的腳手架工具。

上面這部分每一個(gè)都可以獨(dú)立出來單獨(dú)講解。有興趣的讀者可以參考上述工具的官方網(wǎng)站獲取更多信息。

下面來說幾個(gè)其他方面的NodeJS相關(guān)的軟件包。

1. 多版本共存 n/nvm

大多數(shù)情況,我們只需面對(duì)單一的NodeJS版本。等到時(shí)機(jī)成熟,再統(tǒng)一把NodeJS版本升級(jí)到更高版本。

不過筆者就曾經(jīng)遇到過一個(gè)年久失修失修的項(xiàng)目需要重新維護(hù)的情況。此時(shí)需要把NodeJS版本切到老版本。同時(shí),我們也不想舍棄大多數(shù)項(xiàng)目運(yùn)行的新版本NodeJS環(huán)境。

這種情況可以使用n或nvm。下圖展示了,用n下載并切換到一個(gè)新版本的過程。

除了下載之外,n還提供了列表的方式切換多個(gè)版本,以及刪除某個(gè)版本的方法。讀者可以在安裝之后使用n -h查看所有可用參數(shù)。

n采用bash編寫。但提供了一個(gè)npm倉庫安裝的入口,可以使用大家傳統(tǒng)意義的npm安裝法進(jìn)行全局安裝,前提是你必須有一個(gè)可以運(yùn)行的NodeJS環(huán)境。

  1. npm install -g n 

或者在沒有NodeJS的環(huán)境下,可以使用n-install腳本。安裝只需運(yùn)行:curl -L https://git.io/n-install | bash。

如果是windows用戶,在windows10下面可以安裝wsl來獲得Linux腳本運(yùn)行環(huán)境,官方倉庫的一個(gè)issues,對(duì)此有一個(gè)操作說明2。

對(duì)windows10以下的用戶,可以考慮折騰下Cygwin。

除了n之外,還有一個(gè)管理工具為nvm,也是采用bash腳本編寫。安裝亦可使用安裝腳本來完成。如:

  1. curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash 或 wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash 

。這里的v0.34.0是版本號(hào),可能會(huì)隨著版本迭代而變化。

使用windows的讀者,除了上述wsl和Cygwin之外,可以考慮使用nvm-windows3這個(gè)用Golang編寫的版本。

就目前的新版本來說,n和nvm的都會(huì)嘗試處理公共的依賴庫,然而處理方式是不一樣的。

n和nvm都會(huì)在使用某個(gè)版本時(shí)將此版本的NodeJS下載至本地,不同的是:n將嘗試用新版本代替系統(tǒng)路徑中,關(guān)鍵路徑如bin、lib、include、share的包。nvm則是保留每一個(gè)版本的副本,并將NodeJS的系統(tǒng)路徑指向.nvm維護(hù)的沙箱地址。

從處理上,nvm顯得更輕量和高效,但是需要修改系統(tǒng)的PATH,這一步nvm腳本會(huì)自動(dòng)完成。n則無需入侵系統(tǒng)路徑,但每次修改時(shí)候均需操作系統(tǒng)路徑,且此時(shí)使用sudo n運(yùn)行,避免因權(quán)限不足,拒絕向系統(tǒng)路徑復(fù)制。

由于nvm會(huì)修改PATH地址,所以如果同時(shí)默認(rèn)安裝nvm和n,n會(huì)運(yùn)轉(zhuǎn)不正常。一種方案是避免同時(shí)安裝,另外可以手動(dòng)修改PATH,使默認(rèn)的NodeJS路徑先于nvm的系統(tǒng)路徑,如修改PATH片段為:

  1. /usr/local/bin:/Users/leon/.nvm/versions/node/v10.6.0/bin: 

2. 執(zhí)行輔助 nodemon/npx

nodemon是一個(gè)執(zhí)行器,意義在于,如果版本變化或者程序變化,無需重新啟動(dòng)。這在開發(fā)時(shí)候非常有用。

nodemon還可以指定運(yùn)行的端口,如:

  1. nodemon ./server.js localhost 8080 

除了控制NodeJS包之外,nodemon還可以控制非NodeJS腳本,比如:nodemon --exec "python -v" ./app.py,將監(jiān)控app.py的內(nèi)容,并在最開始以及發(fā)生變化時(shí)候,調(diào)用python -v進(jìn)行解析。當(dāng)然,如果你的app.py指定了shebang,也可以不需指定解析函數(shù)。

nodemon有很多靈活的配置,通過這些配置,可以實(shí)現(xiàn)環(huán)境變量設(shè)置、延遲啟動(dòng)、命令執(zhí)行、監(jiān)控定制擴(kuò)展名、優(yōu)雅重啟、事件監(jiān)聽等功能。做法是在需要這些配置的目錄下,提供相關(guān)的配置nodemon.json,也可以在package.json中通過nodemonConfig字段指明。

在這里4 有官方提供的一份配置文件的樣例,供讀者參考。

再來說說npx。什么是npx呢?簡單說,就是找到并運(yùn)行一個(gè)包,并且“用完即走”。

這里有兩層意思:

  • 找到。從哪里找:先是當(dāng)前的依賴,然后是PATH,還找不到就到網(wǎng)上找來安裝。
  • 用完即走。即使從網(wǎng)上安裝的,運(yùn)行完就會(huì)刪掉,不會(huì)留下運(yùn)行的包。 讀者可以試著運(yùn)行下:npx github:piuccio/cowsay "awesome npx"體驗(yàn)下。

這實(shí)在是居家旅行、開發(fā)調(diào)試的利器。比如我要在當(dāng)前目錄下開一個(gè)http服務(wù),可以直接運(yùn)行:npx http-server。

之后就可以直接在瀏覽器訪問這個(gè)地址進(jìn)行調(diào)試了。

另外,如果你需要臨時(shí)用一個(gè)老版本的node來運(yùn)行某個(gè)腳本,也可以祭出npx,這個(gè)node會(huì)被臨時(shí)安裝、臨時(shí)使用、用完即走。

  1. npx -p node@6 npm init 

3. 切換NodeJS注冊(cè)表 nrm/yrm

nrm/yrm維護(hù)了一個(gè)列表,包括npm主站和其他鏡像??梢允褂胣rm/yrm use 快速切換,以達(dá)到最快的下載速度。nrm維護(hù)的是npm的注冊(cè)表,yrm維護(hù)的是yarn注冊(cè)表。

輔助編寫NodeJS包

除了直接用大神們寫好的命令之外,我們也可以按照自己的需求定制自己需要的NodeJS包。我們知道,命令行其實(shí)也是一種人機(jī)交互,因此,交互上有很多可以借鑒的效果。編寫者只需將包倒入就可以使用這些交互效果。這里筆者給大家推薦幾個(gè)包。

1. 命令行參數(shù)讀取 commander

命令行的一個(gè)特點(diǎn)就是根據(jù)參數(shù)的不同調(diào)整運(yùn)行策略。然而處理命令行輸入以及驗(yàn)證是一個(gè)非常繁瑣的事情。為此,TJ大神曾經(jīng)創(chuàng)立了commander包。最基礎(chǔ)的用法如下:

  1. var program = require('commander'); 
  2.  
  3. program 
  4.   .version('0.1.0') 
  5.   .option('-p, --peppers', 'Add peppers') 
  6.   .option('-P, --pineapple', 'Add pineapple') 
  7.   .option('-b, --bbq-sauce', 'Add bbq sauce') 
  8.   .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') 
  9.   .parse(process.argv); 
  10.  
  11. console.log('you ordered a pizza with:'); 
  12. if (program.peppers) console.log(' - peppers'); 
  13. if (program.pineapple) console.log(' - pineapple'); 
  14. if (program.bbqSauce) console.log(' - bbq'); 
  15. console.log(' - %s cheese', program.cheese); 

默認(rèn)地,commander會(huì)自動(dòng)創(chuàng)建-h的幫助文件,即利用每一個(gè)option的輸入產(chǎn)生幫助文案。

用戶的每一個(gè)輸入,都會(huì)放置在program對(duì)應(yīng)option長名的字段的駝峰形式上,如果沒有提供長名,則放在短名字段上。上例中,如使用: testcommander -p 111 -P 222 -b 333則依次存儲(chǔ)在program的peppers、pineapple和bbqSauce上。

同時(shí),commander提供多種驗(yàn)證方式,如正則表達(dá)式:

  1. program.option('-s --size <size>', 'Pizza size', /^(large|medium|small)$/i, 'medium') 

則指定只能輸入特定的值。

同時(shí),commander提供一個(gè)方案,允許用戶設(shè)置子命令。commander稱之為Git風(fēng)格的子命令。

  1. var program = require('commander'); 
  2.  
  3. program 
  4.   .version('0.1.0') 
  5.   .command('install [name]', 'install one or more packages') 
  6.   .command('search [query]', 'search with optional query') 
  7.   .command('list', 'list packages installed', {isDefault: true}) 
  8.   .parse(process.argv); 

這個(gè)例子中,假設(shè)命令行名字為pm,則當(dāng)用戶輸入pm-install、pm-search或pm-list時(shí)候,commander會(huì)嘗試在入口文件的同一級(jí)目錄找到install、search或list,并交給這個(gè)文件去執(zhí)行。

2. 進(jìn)度條 progress

在編寫web程序時(shí)候,大家經(jīng)常會(huì)展示一個(gè)進(jìn)度條。用以緩解用戶在等待時(shí)候的焦慮。其實(shí)在命令行程序中也會(huì)有這種交互方式。比如wget就會(huì)在下載過程中給出進(jìn)度提示。

在NodeJS中也有這樣的效果可以使用。這就是progress包。下面的代碼,運(yùn)行結(jié)果是下載CentOS安裝盤。在下載之中,會(huì)實(shí)時(shí)打印進(jìn)度:

  1. const ProgressBar = require("progress") 
  2. const request = require("request") 
  3. const progress = require("request-progress") 
  4. const fs = require("fs") 
  5.  
  6. const download = (url, headers, target, totalSize) => { 
  7.     let percent = 0 
  8.  
  9.     const bar = new ProgressBar('下載中: ├:bar┤ 完成:percent 預(yù)估完成時(shí)間:eta秒 用時(shí):elapseds', { 
  10.         total: 100, 
  11.         complete: "█", 
  12.         incomplete: "─", 
  13.         width: 60 
  14.     }) 
  15.  
  16.     let opt = { 
  17.         headers, 
  18.         url: url 
  19.     } 
  20.  
  21.     return new Promise((resolve, reject) => { 
  22.         progress(request.get(opt)) 
  23.             .on('progress', function (state) { 
  24.                 let progressFix = ((state.percent) * 100).toFixed(2) 
  25.                 delta = progressFix - percent 
  26.                 bar.tick(delta) 
  27.                 percent = progressFix 
  28.             }) 
  29.             .on("error", () => { 
  30.                 return reject() 
  31.             }) 
  32.             .on('end', () => { 
  33.                 bar.tick(100 - percent) 
  34.                 console.log('\n') 
  35.                 return resolve(target) 
  36.             }) 
  37.             .pipe(fs.createWriteStream(target)); 
  38.     }) 
  39.  
  40. const foo = { 
  41.     getHeaders: () => { 
  42.         const headers = { 
  43.             'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 
  44.             'Accept-Charset': 'UTF-8,*;q=0.5', 
  45.             'Accept-Encoding': 'gzip,deflate,sdch', 
  46.             'Accept-Language': 'en-US,en;q=0.8', 
  47.             'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0' 
  48.         } 
  49.  
  50.         return Object.assign({}, headers) 
  51.     }, 
  52.  
  53.     download: function (url, target, totalSize){ 
  54.         let headers = this.getHeaders() 
  55.         headers = Object.assign(headers) 
  56.  
  57.         download(url, headers, target, totalSize) 
  58.     } 
  59.  
  60.  
  61. foo.download("http://mirrors.cmich.edu/centos/7.6.1810/isos/x86_64/CentOS-7-x86_64-DVD-1810.iso", 
  62.     "CentOS-7-x86_64-DVD-1810.iso", 4508876.8 
  63.     ) 

運(yùn)行的結(jié)果如圖:

這個(gè)包的核心就是根據(jù)內(nèi)置和自定義的token在命令行打印出相應(yīng)的字符,用以完成交互。

3. 交互著色 chalk

chalk是一個(gè)命令行交互的著色工具。在命令行支持的情況下,可以支持最多16位色域(前提是命令行終端可以支持)。一般可以配合console.log使用,如:

  1. const chalk = require('chalk'); 
  2. const log = console.log; 
  3.  
  4. // Combine styled and normal strings 
  5. log(chalk.blue('Hello') + ' World' + chalk.red('!')); 

筆者曾經(jīng)做過一個(gè)在命令行下顯示圖片的程序,就是利用的chalk和console.log進(jìn)行的配合。

4. 交互式問答 inquirer

在需要不斷的同用戶進(jìn)行交互式問答,并根據(jù)用戶的輸入進(jìn)行驗(yàn)證和路徑選擇,這個(gè)時(shí)候inquirer是非常趁手的工具。它內(nèi)置了單選、多選、問答等多種交互方式。大家可以感受下:

甚至可以通過插件實(shí)現(xiàn)suggest:

vue框架的腳手架vue-cli是一個(gè)使用inquire的案例,讀者可以通過閱讀源碼,感受下大神出神入化的使用。

5. 小圖標(biāo) ora

ora打印出一個(gè)優(yōu)雅的文本小圖標(biāo),用于在各種情況下給出用戶優(yōu)雅而清晰的提示。用法很簡單:

  1. const ora = require('ora'); 
  2.  
  3. const spinner = ora('Loading unicorns').start(); 
  4.  
  5. setTimeout(() => { 
  6.     spinner.color = 'yellow'
  7.     spinner.text = 'Loading rainbows'
  8. }, 1000); 

6. 命令行玩瀏覽器 puppeteer

puppeteer是谷歌開發(fā)的無頭瀏覽器,使得命令行亦可操作瀏覽器,并能根據(jù)瀏覽器的執(zhí)行結(jié)果進(jìn)行進(jìn)一步操控。因?yàn)閜uppeteer源自官方,所以之前類似項(xiàng)目PhantomJS的開發(fā)者決定不再更新PhantomJS。

目前puppeteer已經(jīng)廣泛用于前端測試,端對(duì)端測試,以及爬蟲。

鑒于篇幅無法展開介紹,讀者可以參考其官方文檔5。同時(shí),奇舞周刊中黃小璐老師的的這篇文章6以及李光釗老師的這篇文章7都曾經(jīng)介紹過puppeteer的使用。

發(fā)布NodeJS包

寫好的NodeJS包需要發(fā)布出去,才能給大家使用。npm publish就是為了這個(gè)需求而產(chǎn)生的。為了發(fā)布你需要在npm上注冊(cè)用戶,并登錄,然后發(fā)布就好了。npm的詳情頁面以及各個(gè)鏡像會(huì)在一段時(shí)間內(nèi)自動(dòng)更新。

如果你的NodeJS包,是使用尚未廣泛支持的語法寫成的。那么需要在package.json的script字段加入prepublish命令,調(diào)用babel等預(yù)編譯器處理,使得程序可以有更多的兼容性。

對(duì)于希望用戶在全局使用的命令,要注意在根目錄寫好入口,一般是在package.json中的bin字段,指定入口文件。在安裝時(shí),如果是全局安裝,npm將會(huì)使用符號(hào)鏈接把這些文件鏈接到prefix/bin,如果是本地安裝,會(huì)鏈接到./node_modules/.bin/。

除了通常的包,還有一種是帶有scope的包,vue-cli的3.0版本就是@vue開頭的。這個(gè)scope是組織的名字。每一個(gè)帶有scope的包有公有和私有之分,私有的需要付費(fèi)給npm。

目前npm的讀寫權(quán)限策略如下:

如果是個(gè)人,可以考慮增加公有的命名空間。如果是企業(yè)付費(fèi)用戶,你在發(fā)布相關(guān)包之前,需要申請(qǐng)成為這個(gè)scope的member。

對(duì)公有scope,首先將包的name改為@scope名字/包名,同時(shí),在發(fā)布時(shí),使用npm publish --access public即可。

小結(jié)

本文簡述了命令行的意義和優(yōu)勢,介紹了解釋型命令行的運(yùn)行機(jī)制,同時(shí)介紹了幾個(gè)NodeJS相關(guān)的命令行工具,推薦了幾款撰寫命令行程序常用的包,最后,概述了發(fā)布包和使用scope的發(fā)布情況。希望給大家的NodeJS命令行相關(guān)開發(fā)和技術(shù)選型,提供一些有用的幫助。

文內(nèi)鏈接:

  • https://poi.js.org/
  • https://github.com/tj/n/issues/511
  • https://github.com/coreybutler/nvm-windows
  • https://github.com/remy/nodemon/blob/master/doc/sample-nodemon.md
  • https://github.com/GoogleChrome/puppeteer
  • https://mp.weixin.qq.com/s/TZgQPKrpIskIgxX3LCXZYw
  • https://mp.weixin.qq.com/s/Xypg-9qZ8OqsPczEKdn6JA

【本文是51CTO專欄機(jī)構(gòu)360技術(shù)的原創(chuàng)文章,微信公眾號(hào)“360技術(shù)( id: qihoo_tech)”】

戳這里,看該作者更多好文

 

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2016-03-28 10:00:09

Swift命令程序

2023-03-31 08:44:55

Go開發(fā)命令

2010-07-15 10:58:23

Perl命令行程序

2015-07-15 10:32:44

Node.js命令行程序

2022-09-27 13:07:41

clickPython命令行

2022-09-23 09:50:45

Python

2009-12-24 14:51:39

Linux命令行

2017-03-08 11:10:39

LinuxShell命令

2009-08-11 09:58:22

Linux命令行Linux命令svn命令

2017-05-25 10:32:40

命令linux系統(tǒng)

2009-07-14 14:03:56

Swing程序

2017-06-15 10:32:56

OracleDBV命令行工具

2021-01-05 06:12:38

Tcpdump工具網(wǎng)絡(luò)

2020-02-13 10:57:59

Python數(shù)據(jù)設(shè)計(jì)

2010-11-24 16:48:39

mysql命令行

2018-01-24 15:42:49

命令功能程序

2021-01-13 05:29:26

命令行

2011-07-21 13:10:59

2009-05-30 09:26:38

AndroidGoogle移動(dòng)OS

2020-12-10 16:16:08

工具代碼開發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)