搞一个Node Cli来提高工做效率

为何要搞

我在1月发表过一篇:从0搭建自动版本管理的Vue组件库,是一篇搭建组件库的todo类型的文章,包括组件库的搭建、配置、打包、发布。随着公司前端基建愈来愈完善,咱们会产出愈来愈多的像这样的前端库,并且类型愈来愈多:组件库、js库、css库,每一个库都须要去从零开始搞搭建配置打包发布,这种重复劳动显然是不合理的,毕竟懒才是第一辈子产力,那么有没有解决这个问题的好法子呢?因而我想到了Node Cli,安装更新简单、流程统一规范、后续功能可挖掘潜力大,取代了重复劳动,让前端组的同窗有更多的时间focus on coding,大喊真香。javascript

目标

在搞以前弄清楚目标能够有效避免作到一半遇到:我是谁?我在哪?我在干吗?的问题,咱们先来看看咱们的cli须要解决哪些具体的问题,我例举几个我工做中遇到的问题:css

  1. 按规则压缩构建产物:库除了要上传到npm之外,还须要上传到静态资源服务器以供一些老旧的项目直接经过标签引入,须要按照必定的路径规则将构建产物压缩成zip包上传(相似/lib/front/projectName/version/xxxx.umd.js),这样每一个项目都要去搞一套打包前删zip包打包完成后生成zip包的逻辑。
  2. 版本控制:从0搭建自动版本管理的Vue组件库里给你们介绍过在项目中使用npm version对项目进行版本控制,每一个项目都要搞一份,在复制第二份的时候我就忍不了了,得抽出来。
  3. 发布配置:每一个项目都须要一份发布的配置,用于给发布平台执行,有可能须要手动修改里面的版本号避免发布失败。
  4. tag:咱们上传静态资源服务器时是能够覆盖文件的,这样有利有弊,好处是库的发布效率很高,缺点是不够安全,须要一套机制来规避风险,为咱们自动打tag,小于等于tag版本的库就老老实实升级布丁版本更新吧。
  5. 初始化库、添加模版组件:每次搭建库时都得从头开始配置webpack、项目结构、tsconfig、lint等,虽然能够复制现有的库作一下修枝剪叶,但哪有cli直接生成一份香。

总结一下,咱们这个Node Cli须要解决:压缩构建产物、自动化版本控制、拉取标准发布配置、自动打tag、下载库模版或者组件模版。前端

以上是我遇到的问题,同窗们最好仍是结合本身的业务场景,看看Node Cli能不能帮你干掉一些重复性工做。vue

开搞

基础框架搭建

Node Cli的原理是使用npm i -g cli-name安装后把包装到全局的node_modules中,在命令行中执行指令后系统会按照node的环境变量去执行对应脚本。java

在cli项目的package.json中加入:node

{
    ...
    "bin": {
        "mycli": "./bin/mycli.js"
    }
    ...
}
复制代码

这样当其余同窗全局安装时,就能直接使用mycli指令执行mycli.js这个脚本了。webpack

咱们本地开发时可使用npm link将项目连接到包文件夹,这样就能方便调试,不用每次都重建。git

接下来看一下mycli.js,在文件顶部添加#!/usr/bin/env node,目的是解决不一样的用户node路径不一样的问题,让系统动态的去查找node来执行这个脚本。web

这里咱们要依赖一些优秀的第三方包了,这里我选择Commander.js,它是node.js命令行接口的完整解决方案vue-cli

#!/usr/bin/env node

const { program } = require('commander')

const { resolve } = require('path')

const res = (command) => resolve(__dirname, '../src/', command) // 读取脚本路径

const version = require('../package.json').version

program.version(version, '-v, --version') // 执行mycli -v 或 mycli --version的时候输出当前版本号

program.command('init').description('init lib').action(() => { // init脚本的描述与执行
    require(res('init'))
})

program.command('build').description('build lib').action(() => { // build脚本的描述与执行
    require(res('build'))
})

program.command('release').description('release lib').action(() => { // release脚本的描述与执行
    require(res('release'))
})

program.parse(process.argv) // 处理输出参数
复制代码

ok,到此为止cli的基本框架就搭好了,接下来就是丰富它的功能。

丰富功能

在功能愈来愈多以后,咱们的cli自己也可能会遇到体量庞大代码结构复杂的问题,这时候咱们能够将单独的功能独立打成npm包,由cli引入这些包,插件化方案能够参考云音乐前端技术团队的文章:Node CLI 工具的插件方案探索(向大佬学习)。

上文提到的须要解决的问题里,我将使用如下三个脚原本解决,主要说一下每一个脚本实现的思路,同窗们仍是根据业务须要本身实现脚本,想象力空间仍是比较大的。

  1. init: 下载库模版或者组件模版
  2. build: 压缩构建产物、自动化版本控制
  3. release: 拉取标准发布配置、自动打tag

先推荐几个第三方库,能够帮助咱们更好更快的实现功能:

功能 说明
request http模块
inquirer 强大的用户命令行交互工具,vue-cli也用的它
shelljs 在node脚本中执行shell命令
chalk 脱离黑白cli,给输出加点颜色
ora 命令行的菊花图,执行耗时操做时咱们不但愿用户觉得cli卡死了
compressing 用来压缩的
node-emoji 给命令行加一些emoji增长一些趣味(???)

init

解决问题:下载库模板和下载组件模板

咱们能够把预设好的库的模板就放在咱们cli的仓库里,或者放在专门的模板仓库里,而后经过gitlab的API去获取下载,在使用gitlab API以前须要去帐号设置里搞来一份private_token,调用API的时候带上这个参数给gitlab作身份验证,而后利用API递归的读取gitlab仓库里的文件,对应的写入到当前目录下,就完成了库模板的下载,期间能够用ora搞点菊花图,用node-emoji多整几个绿色的勾勾增长一下用户体验。

build

解决问题:压缩构建产物、自动化版本控制

使用inquirer跟用户交互,能够向用户提问:使用哪一种npm version升级策略?打包的项目类型?库的名称?多入口的库选择入口文件?打包输出路径?可选的执行脚本?

在cli中咱们是能够经过require(resolve('pathTo/package.json'))去读取用户的package.json的,能够获取用户项目的名称、版本等信息,这些信息能够做为inquirer提问的默认值,毕竟每次打包都要用户输入的话体验太差了,一路回车火花带闪电确定才是最爽的。既然能够获取到用户的package.json,那咱们就能够作一些约定的配置,好比约定用户的package.json里config.cli这个对象就是专门给咱们cli读取使用的参数对象,用户能够写一些定制化的配置。

我在项目中实践的方案是使用inquirer得到的项目信息去拼凑出vue或者webpack的打包命令(公司主要用vue),例如vue组件库的构建,最终会执行

npx vue-cli-service build --target lib --name name --dest path
复制代码

webpack构建会执行

webpack --output-path path
复制代码

在基础的构建命令之上能够从约定的config.cli中读取用户的配置,例如用户有不一样环境打包的须要就能够添加env参数

打包后根据用户package.json的name、version等信息,把构建产物放进/lib/front/projectName/version/xxxx.umd.js而后用compressing压缩成zip包

release

解决问题: 拉取标准发布配置、自动打tag

拉取标准发布配置和init相似,都是去下载一份标准的配置,能够根据用户的package.json进行一些改动再写入。

自动打tag:我为release指令提供了一个可选参数tag,能够经过process.argv读取,读取到tag参数后,使用gitlab API为对应分支打一个tag,后续build和release均可以先检查这个tag版本和用户package.json的版本,提醒用户不要忘记升级版本。

...

cli能够作的事情还有不少,只要想象力足够而且业务有须要,能节省重复劳动时间,均可以集成进cli做为cli的功能使用。

总结

本文向你们介绍了Node Cli的使用场景和基本的框架搭建,提供了几个功能的实现思路。

主要是给出本身在公司前端基建推动过程当中遇到的问题和解决问题的方案,并非业界最佳方案,但愿你们若是有更好的方案和我讨论,上述的方案不必定每一个公司每一个业务都通用,想要借鉴的同窗仍是建议从公司业务出发搞一份适合本身公司的cli。

我是suhangdev,欢迎与我交流前端相关话题,若是文章对你有帮助,请点赞支持噢,谢谢!

相关文章
相关标签/搜索