日常开发中,编写 Node.js 命令行工具来完成一些小任务是很常见的操作。其编写也不难,和日常编写 Node.js 代码并无二致。

package.json 中的 bin 字段

一个 npm 模块,如果在 package.json 中指定了 bin 字段,那说明该模块提供了可在命令行执行的命令,这些命令就是在 bin 字段中指定的。

package.json

{
"bin": {
"myapp": "./cli.js"
}
}

程序安装后会可在命令行执行 myapp 命令,实际执行的就是指定的这个 cli.js 文件。如果是全局安装,会将这个目标 js 文件映射到 prefix/bin 目录下,而如果是在项目中安装,则映射到 ./node_modules/.bin/ 目录下。

比如上面的示例,全局安装后会将 cli.js 映射到 /usr/local/bin/myapp 目录下。

# 查看项目中安装的所有可执行模块
$ ll node_modules/.bin
...
webpack -> ../webpack/bin/webpack.js
...

如果你的 npm 包只提供了一个可执行的命令,可直接将 bin 字段设置为目标文件,此时命令行中可执行的 CLI 命令名为 npm 包名(即 name 字段)。

{
"name": "my-program",
"version": "1.2.5",
"bin": "./path/to/program"
}

所以上面的配置和下面这个配置是等效的。

{
"name": "my-program",
"version": "1.2.5",
"bin": {
"my-program": "./path/to/program"
}
}

执行:

$ my-program 

CLI 命令的编写

为项目添加 README 文件是很常见的操作,每次都从零开始是没必要的。这时候就可以通过创建一个 README 模板,然后写一个 CLI 工具来生成到项目中。这样,将工具安装到全局或通过 npx 就可以方便地完成 README 文件的创建。

$ npx mkreadme
README.md created

初始化项目

$ npm init -y

修改 package.json 文件为如下内容:

{
"name": "mkreadme",
"bin": "./cli.js",
"version": "0.1.0",
"license": "MIT"
}

创建入口文件

$ touch cli.js

入口文件即 bin 字段所指向的文件,它可以是任何文件名,只需要在行首指定运行环境即可。Node.js 的 CLI 命令,期望的运行环境当然是 Node.js。

cli.js

 #!/usr/bin/env node
// 其他代码...

然后添加我们的功能代码,从远端获取一个 README 模板文件到本地。

cli.js

#!/usr/bin/env node

const fs = require("fs");

const https = require("https"); const TEMPLATE_FILE =

"https://raw.githubusercontent.com/wayou/readme-template/master/README.md"; const file = fs.createWriteStream("README.md");

https.get(TEMPLATE_FILE, resposne => {

resposne.pipe(file);

console.log("README.md created");

});

这里,我们将模板文件放远端的一个位置然后通过网络请求下载下来,而不是直接放到 npm 模块中。这样做的好处是后面可以随时更新我们的模板文件而无须重新发布这个 npm 模块。

调试

通过在当前开发目录进行 link 操作可进行本地调试。

$ npm link
link 操作的输出信息
npm WARN mkreadme@0.1.0 No description
npm WARN mkreadme@0.1.0 No repository field. up to date in 3.435s

found 0 vulnerabilities /Users/wayou/.nvm/versions/node/v11.14.0/bin/mkreadme -> /Users/wayou/.nvm/versions/node/v11.14.0/lib/node_modules/mkreadme/cli.js

/Users/wayou/.nvm/versions/node/v11.14.0/lib/node_modules/mkreadme -> /Users/wayou/Documents/dev/github/mkreadme

然后就可以在任何地方执行刚刚创建的 CLI 命令了。

$ mkreadme
README.md created

参数的获取

让命令支持参数可以实现更加灵活的功能。通过 process.argv 在代码中能够获取到来自命令行的输入。但需要注意它返回的参数列表中前两位是 Node.js 的路径和当前项目的路径,从第三个元素开始才是命令中用户输入的数据。

#!/usr/bin/env node

const fs = require("fs");

const https = require("https"); const TEMPLATE_FILE =

"https://raw.githubusercontent.com/wayou/readme-template/master/README.md"; + const [, , ...args] = process.argv; const file = fs.createWriteStream("README.md");

+ const url = args[0] || TEMPLATE_FILE;

+ https.get(url, resposne => {

resposne.pipe(file);

console.log("README.md created");

});

通过添加参数的支持,我们可以让使用者手动指定一个模板地址以下载对应的模板文件。

发布

最后一步就是发布出去,这样所有人就能安装使用了。

$ npm publish --access public

安装与使用

$ npm i -g mkreadme
$ mkreadme
README.md created

除了像上面将命令安装到全局使用外,个人更加推荐的方式是通过 npxnpx 会自动查找本机是否有安装相应模块,如果没有的话,自动去远端查找并执行。通过 npx 就不用安装到本地,每次运行都可以使用远端最新的版本。

$ npx mkreadme
README.md created

后续的优化

示例中只实现了基本的功能,作为一个功能健全的实用工具,可以做以下的优化:

  • 生成时做重名判断,如果已经存在 README 文件则提示是否覆盖。
  • 文件下载和创建过程中的异常处理及提示。
  • 提供并打印帮助信息,对使用者更加友好。
  • 对输出进行格式化,高亮输出相关信息,使信息更易读。

完整的示例

上面示例中的代码可在 mkreadme 这个仓库中找到。同时也发布到了 npm,可直接使用体验该工具。

三方工具

命令行工具能够打印帮助和使用信息是很重要的,如果自己输出的话,会面临格式化这些内容的麻烦。

如果提供的参数很多,解析处理用户输入的参数也是件很麻烦的事。

像参数校验,错误提示及帮助信息的输出,这些命令行工具基本的功能已经有三方库比较成熟地解决了,比如 commander.js。通过这个库可方便地编写更加复杂的命令行工具。

至于将输出信息进行高亮加彩色进行展示,也有相应三方库比如 chalk

相关资源

Node.js 命令行工具的编写的更多相关文章

  1. 一个最简单 node.js 命令行工具

    一个最简单 node.js 命令行工具 node.js cli $ node cli.js xyz # OR $ node cli xyz 接受参数 process.argv js "use ...

  2. Node.js 命令行程序开发资料

    Node.js 命令行程序开发教程http://www.ruanyifeng.com/blog/2015/05/command-line-with-node.html用Node.js创建命令行工具ht ...

  3. Node.js 命令行程序开发教程

    nodejs开发命令行程序非常方便,具体操作方式查看下面几篇文章 http://www.ruanyifeng.com/blog/2015/05/command-line-with-node.html ...

  4. Node.js 命令行程序开发教程 ---------http://www.ruanyifeng.com/blog/2015/05/command-line-with-node.html

    五.yargs 模块 shelljs 只解决了如何调用 shell 命令,而 yargs 模块能够解决如何处理命令行参数.它也需要安装. $ npm install --save yargs yarg ...

  5. node命令行工具—cf-cli

    音乐分享: 钢心 - <龙王> 初喜<冠军>后喜<龙王> (PS:听一次钢心乐队的演出后采访才知道 “龙王”隐喻的是一起喝酒的老铁....) ——————————— ...

  6. 从零开始打造个人专属命令行工具集——yargs完全指南

    前言 使用命令行程序对程序员来说很常见,就算是前端工程师或者开发gui的,也需要使用命令行来编译程序或者打包程序 熟练使用命令行工具能极大的提高开发效率,linux自带的命令行工具都非常的有用,但是这 ...

  7. 如何用Node编写命令行工具

    0. 命令行工具 当全局安装模块之后,我们可以在控制台下执行指定的命令来运行操作,如果npm一样.我把这样的模块称之为命令行工具模块(如理解有偏颇,欢迎指正) 1.用Node编写命令行工具 在Node ...

  8. Node.js躬行记(3)——命令行工具

    一.自定义 创建一个空目录,然后通过npm init命令初始化package.json文件,并按提示输入相关信息或直接回车使用默认信息,生成的内容如下所示. { "name": & ...

  9. 微软开放技术发布针对 Mac 和 Linux 的更新版 Azure Node.JS SDK 和命令行工具

    发布于 2013-12-04 作者 Eduard Koller 这次为我们使用Linux 的朋友带来了更多关于部署云上虚拟机的消息.今天,微软开放技术有限公司 (MS Open Tech),想与大家分 ...

随机推荐

  1. error LNK2001: 无法解析的外部符号 解决方法

    错误提示:LNK2001 无法解析的外部符号 "public: class el::base::Writer & __cdecl el::base::Writer::construc ...

  2. Java Script 读书笔记 (三) 函数

    1. 函数作用域 在函数内部定义的变量,外部无法读取,称为"局部变量"(local variable). 变量v在函数内部定义,所以是一个局部变量,函数之外就无法读取. 函数内部定 ...

  3. Java 读书笔记 (八) 修饰符

    Java语言提供了很多修饰符,主要分为以下两类: 访问修饰符 非访问修饰符 访问控制修饰符 default (即缺省,什么也不写): 在同一包内可见,不使用任何修饰符.使用对象.类.接口.变量.方法. ...

  4. 「SDOI 2018」反回文串

    题目大意: 求字符集大小为$k$长度为$n$的经循环移位后为回文串的数量. 题解: 这题是D1里最神的吧 考虑一个长度为$n$回文串,将其循环移位后所有的串都是满足要求的串. 但是显然这样计算会算重. ...

  5. BZOJ_3191_[JLOI2013]卡牌游戏_概率DP

    BZOJ_3191_[JLOI2013]卡牌游戏_概率DP Description   N个人坐成一圈玩游戏.一开始我们把所有玩家按顺时针从1到N编号.首先第一回合是玩家1作为庄家.每个回合庄家都会随 ...

  6. java集合框架之Collections

    参考http://how2j.cn/k/collection/collection-collections/369.html Collections是一个类,容器的工具类,就如同Arrays是数组的工 ...

  7. Flask导入静态文件问题

    然而如果使用flask开发web,并且需要在本地导入已经写好的css js 文件或者image一系列,这些文件是静态文件,需要另外建一个文件夹static;并且在html文件修改导入方法,exampl ...

  8. 教你如何使用Java手写一个基于链表的队列

    在上一篇博客[教你如何使用Java手写一个基于数组的队列]中已经介绍了队列,以及Java语言中对队列的实现,对队列不是很了解的可以我上一篇文章.那么,现在就直接进入主题吧. 这篇博客主要讲解的是如何使 ...

  9. ABP框架展示异常信息

    接触ABP框架有一段时间了,也遇到了一些问题,看了官网文档,但是或许是看的不够细致的原因,实际开发中还是遇到了一些问题,耗费了时间去处理,回头一看,原来文档中早已提及. 开发环境:ABP+MPA模式+ ...

  10. sau交流学习社区--看小说的lovebook一个无线端BS应用

    一.前言 loveBook爱上阅读,是一款webapp的读小说等书籍的并且阅读的应用.如果觉得可以,欢迎fork和star. 自己最近在追斗破苍穹电视剧,下班时候在地铁上总听到有人说,斗破苍穹书籍比电 ...