使用 NPM 發佈和使用 CLI 工具

本文是 Node.js 使用淺談的三件套之一工具篇,主要講解了 NPM 命令行接口(CLI)工具發佈的教程,適合閱讀的對象包括:javascript

  • 不熟悉 NPM 工具 和 Node 腳本
  • 不知道如何製做通用的 CLI 工具
  • 只會簡單的發佈和使用 NPM 包

舒適提示:這是一篇 2 年前寫的相對老舊知識體系的舊文章,只用於新人掃盲。完整的源代碼倉庫地址 ziyi2/npm-cli-packagehtml

服務篇可查看 基於 Express 應用框架的技術方案選型淺談前端

Node 腳本

在項目中咱們常常會用到一些 Node 腳本命令來簡化開發的工做量,例如 Element 組件庫的 NPM 腳本命令 build:file (使用腳本生成 Webpack 構建的入口源文件)。vue

簡單的 Node 腳本命令能夠解決當務之急,可是若是實現的功能相對複雜,而且存在多人複用的狀況(例如綁定腳手架或多人拷貝複用),可能會產生如下問題:java

  • 維護性差 (歷史功能 /依賴 / 版本等維護)
  • 污染項目文件夾
  • 增長開發溝通成本

舒適提示:做爲面試官每每能看到簡歷中寫着開發或維護了 xxx 組件,此時會簡單追問該組件如何作到多人複用,會有一些面試者回答手動拷貝...node

爲了解決 Node 腳本命令產生的上述問題,能夠採用 NPM 發包的形式實現通用的 CLI 工具包。react

NPM 包管理器

NPM 包管理器容許用戶將本身編寫的通用包或 CLI 工具上傳到 NPM 服務器,其餘開發人員只須要下載並安裝該 CLI 工具到本地便可使用。webpack

須要注意的是 NPM 包的安裝能夠分爲本地和全局兩種方式。採用本地安裝能夠將發佈的 CLI 工具加入到項目的開發態依賴列表。採用全局方式進行安裝會將 NPM CLI 工具的命令連接到全局執行環境。git

舒適提示:採用本地安裝更多的多是在項目中配合 NPM 腳本使用,而且可固化工具的功能版本。採用全局安裝更多的是進行相似初始化的功能,例如 vue-cli、create-react-app、express-generator 等,此時 Node 腳本不會植入到項目中,而是存放在操做系統的用戶文件夾中。github

你們可能常見的 CLI 工具以下:

接下來將詳細講解如何構建、發佈、安裝和使用一個簡單的 CLI 工具。

CLI 工具

構建

首先新建 NPM CLI 工具的項目文件,執行 npm init 命令建立 package.json 描述文件,須要輸入項目名稱版本描述項目入口文件(發佈 CLI 工具並不須要 main 字段信息,該信息主要用於發佈庫包)、做者信息等:

AppledeMacBook-Pro:npm-cli-package ziyi2$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (npm-cli-package) 
version: (1.0.0) 
description: NPM CLI 工具的發佈和使用
entry point: (index.js) 
test command: 
git repository: (https://github.com/ziyi2/npm-cli-package.git) 
keywords: npm cli
author: ziyi2
license: (ISC) 
About to write to /Users/ziyi2/Git/npm-cli-package/package.json:

{
  "name": "npm-cli-package",
  "version": "1.0.0",
  "description": "NPM CLI 工具的發佈和使用",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ziyi2/npm-cli-package.git"
  },
  "keywords": [
    "npm",
    "cli"
  ],
  "author": "ziyi2",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/ziyi2/npm-cli-package/issues"
  },
  "homepage": "https://github.com/ziyi2/npm-cli-package#readme"
}


Is this OK? (yes) 
複製代碼

舒適提示: NPM 自己就是一個 CLI 工具。

輸入信息後生成的 package.json 描述文件以下:

{
  "name": "npm-cli-package",
  "version": "1.0.0",
  "description": "NPM CLI 工具的發佈和使用",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ziyi2/npm-cli-package.git"
  },
  "keywords": [
    "npm",
    "cli"
  ],
  "author": "ziyi2",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/ziyi2/npm-cli-package/issues"
  },
  "homepage": "https://github.com/ziyi2/npm-cli-package#readme"
}

複製代碼

其次須要配置 PATH 路徑的可執行文件,在 package.json 裏配置 bin 屬性,該屬性對應的是可執行文件的路徑。例如將 bin 對應的可執行文件路徑配置爲當前項目下的 src/index.js

"bin": {
   // npm-cli-package 是一個可執行的命令,該命令指向了 src/index.js 腳本
   // 這裏暫時還不清楚該腳本的環境解釋器
   "npm-cli-package": "src/index.js"
 },
複製代碼

舒適提示:當執行 npm link 或者安裝 CLI 工具時,NPM 會爲 bin 配置的文件建立一個軟連接。 對於 Windows 系統,全局安裝默認會在 C:\Users\{username}\AppData\Roaming\npm 目錄下,局部安裝則會在項目的 ./node_modules/.bin 目錄下。

配置 bin 屬性的模塊路徑後,能夠開始設計可執行文件。爲了使入口文件使用 Node 做爲解釋程序,須要在文件頭部寫入 #! /usr/bin/env node,目的是使用 env 來尋找操做系統中的 Node 啓動路徑,並將 Node 做爲可執行文件的環境解釋器。例如在 src/index.js 入口文件寫入一個打印信息的 Node 腳本:

#! /usr/bin/env node
console.info('npm-cli-package:', '1.0.0')
複製代碼

舒適提示:在 env 中包含了一些環境變量,包括咱們安裝的一些軟件執行路徑等,所以可使用 env 來找到不一樣操做系統上的 Node 執行路徑,從而讓文件可被正常的解釋和執行。

軟連接

CLI 工具設計完成後,接下來是測試它可否被正常使用,此時能夠經過 npm link 命令將其連接到全局執行環境,從而在系統的任意路徑下可使用該 CLI 工具。執行 npm link

// Windows
PS C:\Users\ziyi2\Desktop\npm-cli-package> npm link
up to date in 0.428s
C:\Users\ziyi2\AppData\Roaming\npm\npm-cli-package -> C:\Users\ziyi2\AppData\Roaming\npm\node_modules\npm-cli-package\src\index.js
C:\Users\ziyi2\AppData\Roaming\npm\node_modules\npm-cli-package -> C:\Users\ziyi2\Desktop\npm-cli-package

// MAC OS X
AppledeMacBook-Pro:npm-cli-package ziyi2$ npm link
npm notice created a lockfile as package-lock.json. You should commit this file.
up to date in 4.113s
found 0 vulnerabilities

/usr/local/bin/npm-cli-package -> /usr/local/lib/node_modules/npm-cli-package/src/index.js
/usr/local/lib/node_modules/npm-cli-package -> /Users/ziyi2/Git/npm-cli-package
複製代碼

當執行 npm link 後,能夠看到在 Mac 下該命令主要作了兩件事:

  • 爲可執行文件 src/index.js 建立一個軟連接,將其連接到 /usr/local/bin/<package>( Windows 下是 C:\Users\{username}\AppData\Roaming\npm\<package>
  • 爲當前項目建立一個軟連接,將其連接到 /usr/local/lib/node_modules/<package>( Windows 下是C:\Users\{username}\AppData\Roaming\npm\node_modules\<package> )

所以在全局環境執行 bin 配置的命令時,會啓用 Node 去執行對應的可執行文件。

舒適提示:若是 bin 不配置執行的命令名稱,默認將使用pageage.json 中的 <name> 字段做爲命令。

此時在任意位置執行 npm-cli-package 命令:

AppledeMacBook-Pro:npm-cli-package ziyi2$ npm-cli-package
npm-cli-package: 1.0.0
複製代碼

能夠發如今當前項目外的任意路徑均可以使用該命令成功打印信息,說明 Node 解釋器和軟連接都設置成功。

舒適提示:Windows 系統能夠在用戶目錄 C:\Users\{username}\AppData\Roaming\npm\node_modules 下查看 npm-cli-package 包的軟連接,而且能夠在 C:\Users\{username}\AppData\Roaming\npm 中找到 npm-cli-package (Shell)和 npm-cli-package.cmd (Cmd)兩個可執行文件。

發佈

經過 npm link 以及命令行的使用測試,發現工具的設計沒有任何問題,此時想將該其分享給他人使用,此時能夠利用 NPM 包管理器的發佈機制。在發佈工具以前,須要在 NPM 官網 註冊帳號。註冊成功後,在命令終端中使用 npm login 連接你註冊的帳號( npm login 會將帳號登陸的證書信息保存在本地電腦,從而不須要再次登陸帳號),同時會在 NPM 的網站中生成你當前登陸的 token 信息,登陸後能夠經過 npm whoami 命令查看當前登陸帳號名。

舒適提示:登陸的時候不要使用 NPM 淘寶鏡像地址,須要使用 NPM 官方地址,能夠經過 npm config set registry https://registry.npmjs.org/ 命令設置成 NPM 官方的包發佈地址。

AppledeMacBook-Pro:~ ziyi2$ npm login
Username: ziyi222
Password: 
Email: (this IS public) 673191402@qq.com
Logged in as ziyi222 on https://registry.npmjs.org/.
複製代碼

npm login 後會在 NPM 官網產生 token 信息,接下來使用 npm publish 命令發佈 CLI 工具:

AppledeMacBook-Pro:npm-cli-package ziyi2$ npm-cli-package
npm-cli-package: 1.0.0
AppledeMacBook-Pro:npm-cli-package ziyi2$ npm publish
npm notice 
npm notice 📦  npm-cli-package@1.0.0
npm notice === Tarball Contents === 
npm notice 595B   package.json
npm notice 12.1kB README.md   
npm notice 64B    src/index.js
npm notice === Tarball Details === 
npm notice name:          npm-cli-package                         
npm notice version:       1.0.0                                   
npm notice package size:  5.1 kB                                  
npm notice unpacked size: 12.8 kB                                 
npm notice shasum:        624e3e45667da53d474418907d3250336b56208b
npm notice integrity:     sha512-b77RbfmmF+Gjf[...]MSbp9PL4UUE9w==
npm notice total files:   3                                       
npm notice 
+ npm-cli-package@1.0.0
複製代碼

此時查看 NPM 官網中的我的帳號信息,能夠發現發佈了該工具的 1.0.0 版本。若是須要發佈 Scope 包,須要在 NPM 官網中建立一個組織(例如這裏將 ziyi222 的帳號做爲組織,而後將帳號 ziyi222 重命名成 ziyi222222,並從新登陸帳號):

AppledeMacBook-Pro:npm-cli-package ziyi2$ npm login
Username: ziyi222222
Password: 
Email: (this IS public) 673191402@qq.com
Logged in as ziyi222222 on https://registry.npmjs.org/.
複製代碼

從新修改 package.json 配置文件:

{
  "name": "@ziyi222/npm-cli-package",
  // ...
  "publishConfig": {
    "access": "public"
  }
}

複製代碼

使用 npm publish 發佈:

AppledeMacBook-Pro:npm-cli-package ziyi2$ npm publish
npm notice 
npm notice 📦  @ziyi222/npm-cli-package@1.0.1
npm notice === Tarball Contents === 
npm notice 653B   package.json
npm notice 12.1kB README.md   
npm notice === Tarball Details === 
npm notice name:          @ziyi222/npm-cli-package                
npm notice version:       1.0.1                                   
npm notice package size:  5.1 kB                                  
npm notice unpacked size: 12.8 kB                                 
npm notice shasum:        fac560a42c43d276c9fee17c21887bedaf34bad1
npm notice integrity:     sha512-j/QScEgX+glfS[...]OxhhZcIavUhfg==
npm notice total files:   2                                       
npm notice 
+ @ziyi222/npm-cli-package@1.0.1
複製代碼

安裝和使用

開發者經過 npm install 命令對工具進行全局安裝:

AppledeMacBook-Pro:npm-cli-package ziyi2$ npm install npm-cli-package -g
/usr/local/bin/npm-cli-package -> /usr/local/lib/node_modules/npm-cli-package/src/index.js
+ npm-cli-package@1.0.0
updated 1 package in 12.977s
複製代碼

由安裝打印信息能夠發現,最終 CLI 工具腳本連接指向了 /usr/local/bin/npm-cli-package 。安裝成功以後,能夠在項目中使用 CLI 指定的命令了。

最後

這只是一個簡單的教程示例,真正設計的 CLI 工具可能須要考慮如下一些功能:

  • 幫助信息:用於打印支持的命令、選項參數等
  • 版本信息:用於告知使用者當前的 CLI 版本
  • 環境檢測:用於檢測當前支持的解釋器(Node)版本等
  • 交互面板:提供當前命令的可選項
  • 信息打印:提供各類語義顏色的打印信息
  • ...

所以你可能須要一些額外功能的依賴庫,例如:

  • commander.js - node.js command-line interfaces made easy
  • chalk - Terminal string styling done right
  • Inquirer - A collection of common interactive command line user interfaces
  • node-semver - The semver parser for node (the one npm uses)
  • ...

設計 CLI 工具的真正強大之處在於可以使用 Node 支持的一切能力(例如經常使用的文件系統、http 服務等),從而使得開發者有各類可發揮的空間:

  • 例如一鍵生成腳手架項目
  • 例如一鍵生成 / 更改源碼文件
  • 例如配套各類提供開放 API 的管理平臺(例如 Mock、I18N、主題包管理等)實現本地項目和平臺之間的信息同步能力
  • 例如一鍵生成 Webpack / Babel / Git Hook 等配置文件信息
  • ...

除此以外,若是設計的 CLI 工具對於開發者的使用體驗不夠友好,也能夠設計一個相似於 vue ui的圖形化界面工具來加強用戶的開發體驗(例如以前配合同事設計了一個 lego ui工具來一鍵生成項目的經典佈局頁面)。

招聘小廣告(電線杆不孕不育系列)

Hi,你們好,咱們是阿里巴巴新成立的 BU 政務釘釘事業部(杭州同窗在用的健康碼是我 BU 聯合其餘 BU 共同設計的一個項目),目前還有大量的 Web 前端職位空缺。但願想找我內推或者想了解更多招聘信息的同窗能夠加我微信:18768107826

相關文章
相關標籤/搜索