使用 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

相关文章
相关标签/搜索