10分钟快速搭建出提高生产效率的 CLI 工具

背景

先来说说为什么我要开发一个 CLI 工具

之前因为业务需求,开发过一段时间的 Koa 项目,由于需要不停的在新老项目之间进行切换,也就经常不避免的会产生了一些重复性的工作,比如

  • 创建新项目
  • 集成项目所需依赖
  • 添加各种项目规范
  • 添加各种配置文件
  • 编写大量重复代码
  • 配置项目打包发布
  • ...

结合以上 10086+ 个痛点,经过简单的构思和研究,我开发出了属于自己的 CLI

  • nost-cli:基于 Koa 的 nodeJs 框架

目的很简单,就是为了简化开发流程,提高生产效率。

虽然现成的 node 框架也很香,但是我不管,我就要卷!!!

预览

现已发布至 npm,可通过 npm install -g nost-cli 安装体验!!!

思路

通过 npm package 的形式进行安装使用

  • 创建项目:可以快速帮我创建一个规范的 koa 项目,开箱即用

  • 运行项目:可以帮我在开发环境下运行该项目并进行实时的热更新

  • 打包项目:可以帮我在即将发布生产环境时进行代码生成和压缩

  • 文件创建:

    • 快速创建 router 模版进行请求和参数处理
    • 快速创建 controller 模版进行内部逻辑处理
    • 快速创建 service 模版进行数据库相关操作
    • 快速创建 middleware 模版进行自定义中间件的编写
    • 快速创建 error 模板进行自定义错误处理
    • 快速创建 config 文件用于新增项目配置
  • 信息查看:

    • 版本信息
    • 更多帮助

nost-cli

nost-cli核心步骤实现

第一步:初始化项目并实现通过命令运行该项目

  • 使用 yarn init -y 初始化项目
  • 配置 package.jsonbin 字段
  • 新增 index.js 文件并在顶部写入 #!/usr/bin/env node
  • 通过 npm link 实现软链
  • 命令行中输入 nost 敲回车即可查看相关打印

第二步:添加工具的帮助信息和使用说明

  • 安装 commander 工具库
  • 完善 index.js
index.js 复制代码
#!/usr/bin/env node

const { program } = require('commander')
const { version } = require('./package.json')

program.version(version, '-v, --version', 'Output the current version.')
program.option('-h, --help', 'Output usage information.')

program
  .command('init <project-name>')
  .alias('i')
  .description('Initialization Nost application.')
  .action(async (source, destination) => {})

program
  .command('start')
  .description('Run Nost application.')
  .action(async (source, destination) => {})

program
  .command('build')
  .alias('b')
  .description('Build Nost application.')
  .action(async (source, destination) => {})

program
  .command('info')
  .description('Display Nost project details.')
  .action(async (source, destination) => {})

program
  .command('config <config-filename>')
  .alias('cfg')
  .description('Generate a configuration file.')
  .action(async (source, destination) => {})

program
  .command('controller <controller-filename>')
  .alias('c')
  .description('Generate a controller declaration.')
  .action(async (source, destination) => {})

program
  .command('error <error-types-filename>')
  .alias('e')
  .description('Generate a error declaration.')
  .action(async (source, destination) => {})

program
  .command('middleware <middleware-filename>')
  .alias('m')
  .description('Generate a middleware declaration.')
  .action(async (source, destination) => {})

program
  .command('router <router-filename>')
  .alias('r')
  .description('Generate a router declaration.')
  .action(async (source, destination) => {})

program
  .command('service <service-filename>')
  .alias('s')
  .description('Generate a service declaration.')
  .action(async (source, destination) => {})

program.parseAsync(process.argv)
  • 执行 nost [options] [command] 就可以执行不同的命令

第三步:完善每一个命令对应的操作

1. init | i <project-name>

  • action callback 中的 source 获取输入,通过 fs 模块对进行边界判断
  • 安装 chalk 工具库用来美化命令行的日志打印
  • 安装 ora 工具库用来在命令行与用户进行交互
  • 安装 download-git-repo 工具库用来拉取 Koa 项目模板
  • <project-name> 更新到 package.json

2. start

  • 通过 child_process 模块执行项目中的脚本用于在开发环境运行项目

3. build | b

  • 通过 child_process模块执行项目中的脚本通过打包工具生成生产代码

4. info

  • 通过 figlet 在线生成"高大上"的命令行 Banner

5. config | cfg <config-filename>

  • 通过 fs 模块在项目的 config 目录中创建配置文件

6. controller <controller-filename>

  • 通过 fs 模块在项目的 controller 目录中根据控制器模板创建指定的控制器文件
js 复制代码
const controllerName = source[0].toUpperCase()}${source.substring(1)
const controllerTemplate = `
import { Context, Next } from 'koa'
class ${controllerName}Controller {
  async list(ctx: Context, next: Next) {
    ctx.body = 'list'
    await next()
  }
    
  async info(ctx: Context, next: Next) {
    ctx.body = 'info'
    await next()
  }
}

const ${source}Controller = new ${controllerName}Controller()
export default ${source}Controller
`  

7. error | e <error-types-filename>

  • 通过 fs 模块在项目的 error 目录中创建 errorTypes 文件
js 复制代码
const errorTypesTempalte = `
export const ERRORTYPE = 'error message'
`

8. middleware | m <middleware-filename>

  • 通过 fs 模块在项目的 middleware 目录中根据中间件模板创建指定的中间件文件
js 复制代码
const middlewareTemplate = `
import { Context, Next } from 'koa'

export const customMiddleware = async (ctx: Context, next: Next) => {
  // do something...
  console.log(ctx.request.params, ctx.request.body)
  await next()
}
`

9. router | r <router-filename>

  • 通过 fs 模块在项目的 router 目录中根据路由模板创建指定的路由文件
js 复制代码
const routerTemplate = `
import Router from '@koa/router'

const router = new Router({ prefix: '/${source}' })

router.get('/list')
router.post('/list/:id')

export default router
`    

10. service | s <service-filename>

  • 通过 fs 模块在项目的 service 目录中根据模型模板创建指定的路由文件
js 复制代码
const serviceName = source[0].toUpperCase()}${source.substring(1)
const serviceTemplate = `
// import connection from "../mysql"
class ${serviceName}Service {
  // 操作 mysql 获取数据
  // async list() {
  //     const statement = 'SELECT * FROM ${source};'
  //     const [result] = await connection.execute(statement)
  //     return result
  // }
  async list() {
    return []
  }
}
const ${source}Service = new ${serviceName}Service()
export default ${source}Service
`

第四步:编写一个简单的 markdown 并执行 npm publish 进行发布

Koa 项目模板

  • 项目概述
    • 包管理工具使用 yarn
    • 默认使用 ts 进行编写
    • 规范使用 eslint
    • 格式化使用 prettier
    • 打包使用 rollup
  • 源码(src)目录结构
    • main.ts - 入口文件
    • app.ts - 创建 app 并导出
    • router - 路由目录
    • controller - 控制器目录
    • service - sql 目录
    • config - 配置目录
    • middleware - 中间件目录
    • mysql - sql-connection 目录
    • error - 错误处理目录
  • 完整目录结构
md 复制代码
.
├── .eslintignore
├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── env.d.ts
├── package-lock.json
├── package.json
├── rollup.config.mjs
├── src
│   ├── app.ts
│   ├── config
│   │   ├── db.config.ts
│   │   └── server.config.ts
│   ├── controller
│   │   └── user.controller.ts
│   ├── error
│   │   ├── index.ts
│   │   └── user.errorTypes.ts
│   ├── main.ts
│   ├── middleware
│   │   ├── user.middleware.ts
│   │   └── wrapper.middle.ts
│   ├── mysql
│   │   └── index.ts
│   ├── router
│   │   ├── index.ts
│   │   └── user.router.ts
│   └── service
│       └── user.service.ts
├── tsconfig.json
└── yarn.lock

总结

有实践! 有思考! 有收获! 有提高!!

相关推荐
gnip4 分钟前
SSE技术介绍
前端·javascript
掘金安东尼12 分钟前
蔚来 600 亿研发成本,信还是不信。。
面试·程序员·github
yinke小琪19 分钟前
JavaScript DOM节点操作(增删改)常用方法
前端·javascript
枣把儿23 分钟前
Vercel 收购 NuxtLabs!Nuxt UI Pro 即将免费!
前端·vue.js·nuxt.js
望获linux24 分钟前
【Linux基础知识系列】第四十三篇 - 基础正则表达式与 grep/sed
linux·运维·服务器·开发语言·前端·操作系统·嵌入式软件
爱编程的喵26 分钟前
从XMLHttpRequest到Fetch:前端异步请求的演进之路
前端·javascript
喜欢吃豆28 分钟前
深入企业内部的MCP知识(三):FastMCP工具转换(Tool Transformation)全解析:从适配到增强的工具进化指南
java·前端·人工智能·大模型·github·mcp
豆苗学前端31 分钟前
手把手实现支持百万级数据量、高可用和可扩展性的穿梭框组件
前端·javascript·面试
不见_31 分钟前
不想再写周报了?来看看这个吧!
前端·命令行
yinke小琪33 分钟前
JavaScript 事件冒泡与事件捕获
前端·javascript