记录我第一次开发和发布npm包
15 May 2017
写了不少node脚本,虽说不咋复杂,但用的node_module也不少,想想还没自己做过一个npm包发布上去呢,刚好有了个想法:启动apache
或者resin
来启动本地web服务,虽然可以,但总是离不开各种配置文件,后来学习了koa-static
,发现原来写个脚本也就能启动本地web服务,于是开始了koa-static
的脚本启动方式,但每换一个目录,要么就是准备多一份脚本要么就是脚本调整一下项目路径,懒癌发作起来,这也是不能忍的,于是想着不如做一个命令行工具,直接通过命令的方式启动服务,那就方便了。(后来加了配置文件来做更多功能)
场景
这样一个脚本就能启动一个静态web服务了
以这个为出发点,我需要的命令行,应该是可以通过进入到项目目录(cd
指令),然后通过工具指令运行,即时启动类似上述的脚本代码完成服务启动。
准备工作
- 从上面脚本可以看出,服务主要需要的输入元素是:目录、端口号。这两个元素在命令行中应当以参数的形式存在,而且带有默认值。
- 需要用到的基本依赖: commander、koa、koa-static
关于koa
,有份不错的资料介绍,介绍其原理等等,相当不错,值得一读
关于commander
, 在带有子命令的情况,一般是要建立 命令名+'-'+子命令名.js
文件来写子命令的实现。
关于github
,项目托管在github,方便开源和开发管理。
npm包的一般开发流程:定义好项目目录-> 生成package.json-> 下载依赖包->编写代码->跑测试->发布
命令行工具的开发细节
因为是命令行工具,我们需要让脚本能被系统从环境变量中检索出来,关于环境变量的定义,这个时候需要项目根目录建立bin目录放置命令行工具脚本,在package.json定义bin字段,"bin":{"qls":"bin/qls.js"}
然后通过 npm link
之后
我们就可以直接在命令行窗口里敲击qls
命令 ,并运行。其实际效果就是去执行对应的bin/qls.js
脚本了。(取消的话,可以用npm unlink
)
进入开发
在准备工作做好之后,即可以开始入门敲代码了,确认好项目结构,执行启动服务的脚本 ,应该承担起封装对象并运行启动服务的职责,该部分不做额外的接受参数操作,而是通过其被调用时传参来获取输入信息,如上面提到的目录路径和端口号,暂定为index.js。
命令行脚本
设定主要指令格式:
$ qls run # 启动服务,默认当前目录和端口号
$ qls run -p 10089 # 使用10089端口号
$ qls run -d 项目路径 # 指定项目路径,主要是减少要进入比较长路径的项目的cd命令操作
$ qls init # 配置文件并初始化
要实现这几个指令,其实很简单,主要入口脚本 qls.js
, 子命令脚本qls-run.js
、qls-init.js
qls.js
qls-init.js
qls-run.js
在使用commander过程中,遇到的几个奇怪点,一个是用其自带的帮助提示和显示usage时,会把文件名(不带后缀)显示,于是我才把主文件名改为qls.js
。 而子命令文件需要以 command +'-'+subcommand+'.js'
的方式命令,否则执行时会报找不到对应文件。
子命令才是命令行的主体逻辑,实际就是通过运行业务逻辑脚本模块内容来执行的。
主体逻辑实现
主体逻辑说白了就是一开头说的koa脚本那几行实现,只不过这里加上了参数判断以及判断端口占用问题。
写到这里,基本的qls命令行就完成了。后续我又加载上了proxy(参考vue-cli的proxyTable跨域接口代理)。
代码检查-ESLint
入门ESLint
我的配置:
module.exports = {
"extends": "eslint:recommended",
"env": {
node: true,
es6: true
},
"rules": {
"no-console": 0,
"func-names": 0,
"no-tabs":0,
"indent":0,
"prefer-arrow-callback":0,
"linebreak-style":0
}
}
单元测试
参考资料
由于项目主要是启动服务,所以测试需要用到supertest
来测试http请求相关内容。
发布npm
项目基本完善完可以发布时,进入项目目录,登录npm账户(需要去npm注册账号)
根据提示输入用户名和密码。注意:如果你有用nrm
对npm源做切换的操作,先把源切回npm原来的地址,不然貌似发布不成功。
发布命令:
后续更新,每次修改代码之后,在项目目录下直接输入指令npm version patch
,将会把package.json的version更新,(如果项目还是用了git管理的话,package.json的更新还是自动commit)最后继续npm publish
即可把更新内容发布到npm上去了。
参考
后续
后面开发了proxy代理接口后,本想接着做mock数据,不过在做proxy过程中,遇到post请求时,自己一开始挖坑先做post数据解析导致proxy后实际接收方得不到正确的post数据,虽然修正了,但如果做mock数据,避免不了在实现响应数据结合请求数据渲染时,再次遇到要先解析post数据的问题,暂时就搁置了,先顺手学习一下单元测试的编写以及koa
的进阶……