Node Cli 入門

第一行代碼

命令行上簡單的輸入一行代碼,而後立刻就創建了一個模板工程,這種方式想一想都會以爲很酷。例如使用vue-cli工具的vue命令能夠建立一個高配的模板工程。做爲第一行代碼咱們就先不玩那麼高深的,就來個hello worldhtml

咱們能夠新建一個項目目錄叫作test,而後進入該目錄下npm init一路執行回車,最後在項目目錄下新建一個bin文件夾,建立一個hello.js文件,而後寫上:前端

#!/usr/bin/env node

console.log("hello world");

修改package.json文件:vue

{
  "name": "test",
   "bin": {
    "test": "bin/hello.js"
  }
}

而後執行 npm link 命令:node

$ npm link
...
C:\Users\Administrator\AppData\Roaming\npm\test -> C:\Users\Administrator\AppData\Roaming\npm\node_modules\test\bin\hello.js
C:\Users\Administrator\AppData\Roaming\npm\node_modules\test -> E:\github-code\test

命令行執行test,會打印出:hello world。git

node 全局路徑

咱們的hello world程序跑完了,這裏重點聊聊兩個問題:github

  • #!/usr/bin/env node在這裏有什麼做用?vue-cli

  • npm link 到底在這裏有什麼做用?npm

要理解這兩個問題,首先咱們要知道操做系統中都會有一個 PATH 環境變量,當系統調用一個命令的時候,就會在PATH變量中註冊的路徑中尋找,若是註冊的路徑中有就調用,不然就提示命令沒找到。咱們能夠經過process.env獲取本機系統中全部的環境變量。json

對於模塊的載入及緩存機制能夠分爲如下幾中狀況:segmentfault

  • 載入內置模塊(A Core Module)

  • 載入文件模塊(A File Module)

  • 載入文件目錄模塊(A Folder Module)

  • 載入node_modules裏的模塊

  • 自動緩存已載入模塊

這裏咱們重點關注的是載入node_modules裏的模塊。若是模塊名不是路徑,也不是內置模塊,Node將試圖去當前目錄的node_modules文件夾裏搜索。若是當前目錄的node_modules裏沒有找到,Node會從父目錄的node_modules裏搜索,這樣遞歸下去直到根目錄。

咱們經過全局命令安裝的模塊會保存在全局目錄下,如:

npm install -g vue-cli

咱們能夠在{prefix}/node_modules目錄下找到vue-cli文件夾,這個就包含了vue-cli的包。
對於不一樣的系統,{prefix}值不一樣,這裏咱們可使用npm prefix命令獲取:

npm prefix -g

固然咱們也能夠經過npm config命令的get和set方法操做這個路徑。

那麼再去理解上面的兩個問題就簡單了,#!/usr/bin/env node主要是幫助腳本找到node的腳本解釋器。npm link的做用至關因而將咱們的工程進行了全局安裝,可是不一樣的是咱們能夠在命令行進行使用package.json文件中bin字段下的命令。如上面的test工程經過 npm link,這一步能夠將本地目錄安裝到模塊全局目錄{prefix}/node_modules下,而且會在{prefix}文件夾下生成test文件和test.cmd文件。另外最關鍵的時候會創建連接,當本地目錄如test文件夾變更,全局模塊目錄下的test文件夾也會相應改變,在其餘目錄下調用test命令一樣能夠找到命令。

一樣咱們能夠經過下面的命令卸載模塊:

npm uninstall -g test

處理命令行參數

node process對象一個提供有關當前Node.js進程的信息和控制的全局對象,在node環境下無需經過require()便可調用。

process.argv屬性返回一個數組,其中包含啓動Node.js進程時傳遞的命令行參數。第一個元素是process.execPath, 若是須要訪問argv [0]的原始值,可使用process.argv0,第二個元素將是要執行的JavaScript文件的路徑, 其他元素將是任何其餘命令行參數。

#!/usr/bin/env node
console.log('call %s', process.argv[2]);

而後輸入test hello,打印出call hello

對於命令行參數處理,咱們通常用現成的模塊commander或yargs處理,提供了用戶命令行輸入和參數解析強大功能。這裏咱們就使用輕量級,表達力強大的commander進行處理。

官網:http://tj.github.io/commander...
安裝:

npm install --save commander

commander 特性:

  • 自記錄代碼

  • 自動生成幫助

  • 合併短參數(「ABC」==「-A-B-C」)

  • 默認選項

  • 強制選項​​

  • 命令解析

  • 提示符

commander API:

處理用戶輸入

node提供了標準的命令行輸入的API——readline

const readline = require('readline');
const rl = readline.createInterface(process.stdin, process.stdout);
rl.question('what is your name? ',  function(answer){
    console.log(`name is ${answer}`);
    rl.close();
});

注意:當調用該代碼時,Node.js 程序不會終止,直到 readline.Interface 被關閉,由於接口在等待 input 流中要被接收的數據。

配合異步流程控制典型的co 模塊使用:

let readlinePrompt = function (query) {
  return new Promise(function (resolve, reject) {
    rl.question(query, function(answer){
      resolve(answer);
    });
  });
};

co(function *() {  
    var template = yield prompt('what is template-name? ');
    var project = yield prompt('what is project-name? ');
    console.log(`template-name is ${template}`);
    console.log(`template-name is ${project}`);
    rl.close();
})

爲了簡便咱們通常都會使用co-prompt或者Inquirer.js之類的模塊。如使用co-prompt模塊咱們能夠這樣寫:

const prompt = require('co-prompt');
co(function *() {  
    var template = yield prompt('what is template-name? ');
    var project = yield prompt('what is project-name? ');
    console.log(`template-name is ${template}`);
    console.log(`template-name is ${project}`);
})

下載git模板

參考vue-cli中下載git模板項目的方法,這裏主要是使用了download-git-repo模塊,以及使用ora模塊顯示下載狀態。

let templateName = program.args[1]
let templateDir = path.join(home, '.plus-templates', templateName.replace(/\//g, '-'))
let clone = program.clone || false

function downloadAndGenerate(template) {
  const spinner = ora('downloading template').start();
  download(template, templateDir, { clone: clone }, function (err) {
    spinner.stop();
    if (err) logger.fatal('Failed to download repo ' + template + ': ' + err.message.trim())
    // generate
  })
}

參考

Node.js的模塊載入方式與機制
教你從零開始搭建一款前端腳手架工具
異步流程控制:7 行代碼學會 co 模塊
【譯】使用Node.js建立命令行腳本工具

相關文章
相關標籤/搜索