【原创】使用Node.js开发Windows下的命令行工具

忙忙碌碌又半年,别人都在做年中总结,回顾上半年点点滴滴的辛酸历程,或辉煌战绩。而我好不容易在时间隧道中捕捉到片刻的闲暇,终于可以做一点自己的事情。最近,其实也是由于项目需要,用Node.js写了一些有助于前端开发的本地小工具,才逐渐意识到Node.js似乎离自己越来越远,于是又想找回与Node.js的那些甜蜜时光。然后,思来想去还是从一个简单的命令行工具开始吧。

为什么做这个尝试?

为什么从一个命令行小工具开始?我也曾问自己这个问题。首先,为了弥补自己在这方面的缺陷。自从接触-学习Node.js以来,除了知道Node.js有开发命令行工具的能力外,仅仅使用过一些开源的Node.js命令行工具,诸如:express、yeoman、gulp、grunt等等。但自己却从未去了解过其中的奥妙。其次,身边各种Mac OS、Linux系统使用者频现,流畅熟练的命令行操作显得格外帅气和高大上,有一种身陷科幻大片的感觉。再次,姑且不说掌握这个技能是否存在其价值,但这毕竟也是一种Node.js的尝试,一项有用的技能,所谓“技多不压身”,学学又何妨?还有最后一点,在我查找这方面的资料的时候,不知道是关键词没选好,还是这方面资料确实少,反正有点难找,索性就把自己的摸索过程记录下来了。

效果预览

Command line tool

实践

通过上面的gif演示,其实你已经读完了本文的所有内容:开发一个npm包,可以让所有人通过npm install命令安装,并且通过命令行直接运行相关指令,处理相应的事务。接下来我们就通过一个跟“Hello world”一样简单的示例,一起来学习。

包目录结构

“无规矩,不成方圆”,任何事物都有其必须遵守的规则。开发一个Npm包,最基本的原则就是需要一个包目录,并创建相应的包配置文件。如示例所示:我们开发了一个名为zwj的包,那么我们就把包目录定义为zwj,接着便可以进入zwj目录,创建名为package.json的包配置文件。命令如下:

1
2
mkdir zwj
cd zwj

然而,当我们创建配置文件的时候,为了确保内容与格式的准确性,建议使用npm内置的npm init命令来创建。执行命令后,根据提示一步一步完成操作即可。当然,如果你非要自己一项一项配置去敲,也不会有人拦着你。

初始化的package.json文件,可以满足我们开发普通包的所有需求,但是对于需要支持命令行操作的包,我们还需要做一些其他的补充。首先,需要在配置文件中增加bin配置,并绑定命令和脚本。而脚本对应的文件位置,可以是包的根目录,也可以是包中其他任意目录下的文件。参考了几个较为有名的npm包,建议将脚本位置放置在名为bin的目录中。

完成了这些之后,当然我们就该考虑实现我们的小工具的具体功能了,所以少不了要创建一些js文件。至此,我们的包目录结构至少应该像下面这样:

包目录基础结构

文件内容简述

有了前面的基础,接下来我们来逐个分析每个文件的内容,更加深入的去理解前面罗列信息。我们先来看一下配置文件的关键内容:

package.json关键配置

这是截取自package.json中的一部分,也是比较关键的一部分,这几个信息几乎是每个完整的npm包必填的配置。从上至下依次表示:包名、版本、包描述、主入口文件、bin【命令行不可少的配置字段】。

然后,我们看下示例中bin/zwj文件中的内容:

1
2
#!/usr/bin/env node
require('../zwj.js');

代码超级简单,总共就这么两行。当然我们也可以在这里书写复杂的逻辑,比如根据命令行参数,调用不同的执行脚本等等。简单解释下这两行代码,第一行是Unix/Linux的写法,简单的说就是告诉程序使用什么东西来解释下面的代码,此处就是告诉系统使用node来执行下面的代码。第二行就简单了,执行加载../zwj.js模块,并返回。也就是说,经过这行代码之后,我们的命令行小工具的具体功能就可以交给zwj.js这个文件去控制了。那么,zwj.js究竟做什么,那这个就要看开发者的意图了,先不管这个,我们先来看看示例代码中的zwj.js做了什么:

1
2
3
var fs = require('fs'),
pwd = process.cwd();
console.log(fs.readdirSync(pwd));

如演示中所示,示例命令行工具的功能便是在控制台显示执行命令目录下的文件列表。process.cwd()得到的是当前执行命令目录的完整路径。

本地调试

至此,用Node.js开发一个命令行工具的内容就讲完了。但是程序开发往往不能一步到位,期间可能存在各种各样未知的不可预测的问题。这时候调试就显得尤为重要了,这也是为什么调试环节在任何一个程序开发项目中不可或缺的原因之一。在Windows下开发命令行工具的测试方式其实很方便,进入本地包根目录,执行:

1
npm install . -g

即可将本地正在开发的包,安装为全局包。而在执行以上命令的过程中,便会在npm全局包目录中生成命令行所需的cmd文件,本例生成zwj.cmd。生成的文件内容大致如下:

命令行可执行文件

而在Unix/Linux中就更简单了,只需在包根目录执行npm link即可。

成功之后,我们就可以直接在命令行输入zwj命令,执行相应的功能了。当然,前提是npm全局包目录被添加到了path环境变量中。通常应该是这样的:

PATH环境变量

而当我们执行命令测试脚本发现问题后,我们在本地包中修改,完成后再次执行前面的安装代码便可以直接覆盖前一次安装,也可以先执行卸载命令:

1
npm uninstall -g zwj

然后再安装即可。

发布与升级

当我们的工具开发完成后,如何发布到社区,如何提供给其他开发者使用,这是我们的最后一步。npm包的发布很简单,原本只需要在包根目录执行:npm publish命令即可。但如果你是第一次发布应用,需要解决好账号登录的问题:先执行npm adduser命令,依次输入用户名、密码和邮箱登录,然后通过npm whoami命令确认登录是否成功。万事俱备之后,再执行npm publish命令,你的包就可以发布到社区与众多开发者共享了!

最后,升级就简单了。本地增加好新的功能,测试通过之后,修改版本号之后,执行:npm publish等待完成即可。

PS:最好给每个包都增加一个README.md文件,写入包的作用,使用方法,更新日志等等。方便使用者查阅。完美~~