1.0.0 • Published 2 years ago

drip-micro v1.0.0

Weekly downloads
-
License
ISC
Repository
-
Last release
2 years ago

简介

本框架在drip-core的基础上添加了基本模块、中间件和工具函数供开发人员使用。

开发规范

1、禁止require或import加载相对路径文件

2、禁止当前服务创建两级路由,需通过添加下级服务创建

3、服务内代码统一按模块进行分类编写,各功能模块职责见下方说明

4、各模块按顺序加载,当前加载顺序依次为: agent/database -> api/model -> service -> controller -> router,前者无法获取后者数据

快速上手

  • step1、创建项目,进入项目根目录

  • step2、安装drip-micro npm i drip-micro

  • step3、添加app.js、server.js文件

// app.js文件
const drip = require('drip-micro');
const app = new drip.App({module});
app.start(3000);
// server.js文件
const drip = require('drip-micro');
const server = new drip.Server({module});
server.start();
  • step4 执行 node app.js

应用场景

框架默认提供router、controller、view、service、model、api、agent、database、schedule等9个功能模块、middleware、utils、context等3个特殊模块以及config通用模块。上述模块的组合使用可应用于如下经典模式和场景。

server应用

router + controller + service + model + database可实现最基本的server应用,model + database建模并读写数据库供service和controller调度并输出。

网关应用

router + controller + service + api + agent可实现最基本的网关应用,api + agent可配置代理网关、获取数据供service和controller调度并输出。

MVC模式

router + controller + view + service + model + database可组成最基本的MVC模式,由model + database组成M,view组成V,router + controller + service组成C。

混合应用模式

上述模块和模式按照规则搭配即可构成混合应用。

功能模块

提供具体功能(如路由、控制层等)的模块,所有功能模块都有启动时和运行时。

启动时代码编写

启动时区域代码的编写有类、异步函数,普通函数3种方式。

启动时区域会传入一个对象,包含app和server两个对象,前者是应用全局的配置对象,后者是当前所在目录微服务的配置对象。

1、类方式

除在启动时需要执行异步代码外,大部分模块都建议采取此种方式。

module.exports = class {
  constructor ({ app, server }) {
    // 启动时
  }
  async index  (ctx, next){
    // 运行时
  }
}
2、异步函数方式

启动时需要执行异步代码的建议采取此种方式

module.exports = async ({ app, server }) => {
  // 启动时
  return {
    index: async (ctx, next) => {
      // 运行时
    }
  }
}
3、普通函数方式

除router、agent、database模块外,其他模块不推荐此种编写方式,建议采用类方式编写。

module.exports = ({ app, server }) => {
  // 启动时
  return {
    index: async (ctx, next) => {
      // 运行时
    }
  }
}

运行时代码编写

运行时代码编写方式根据功能模块的不同而不同,一般情况下为异步函数,入参同koa中间件一样为ctx和next。

具体功能模块说明

view

视图层模块,此模块存放各类视图模板,文件后缀默认为html,默认采用nunjucks作为模板解析引擎。

以view命名的文件或者放入view目录的文件均视为view模块,后者支持多级目录。

举例

// 某server下的./view/index.html,在controller中可通过server.view.index获取。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>{{ title }}</title>
</head>
<body>
{{ content }}
</body>
</html>

controller

控制层模块,用于解析输入,处理后展示到view层或者直接输出。

以controller命名的文件或者放入controller目录的文件均视为controller模块,后者支持多级目录。

在执行区域,controller模块相比其他功能模块多了renderer方法用于自定义配置view解析。

举例

// 某server下的controller.js,后续可在router模块中通过server.controller获取
module.exports = class {
  constructor ({ server, renderer }) {
    this.server = server;
    this.render = renderer({ engine: 'ejs' });
  }
  async index (ctx){
    ctx.body = await ctx.render(this.server.view.index, { title: '蜻蜓FM', content:'首页' });
  }
  async user (ctx){
    ctx.body = await this.render(this.server.view.user, { title: '蜻蜓FM', content:'个人中心' });
  }
}

router

路由模块,提供最基本的路由匹配功能,此模块基于koa-router。

以router命名的文件或者放入router目录的文件均视为router模块,后者支持多级目录。

举例

// 某server下的router.js
module.exports = ({ server }) => {
  const { controller, router } = server;

  router.get('/', controller.index);
}

database

数据库模块,用于配置和连接数据库并供model使用。数据库模块已默认集成mongoose、sequelize以及redis。

以database命名的文件视为database模块,不支持目录方式。

举例

// 某server下的database.js,后续可在model模块中通过server.database获取
module.exports = async ({ mongoose, sequelize, redis, typeorm, server }) => {
  const { config } = server;
  const client = redis.createClient({
    host: config.redis.host,
    password: config.redis.password
  });
  return {
    redis: client
  }
}

model模块

模型层模块,用于从database模块读取数据库配置、定义各种数据模型供service或controller使用。

以model命名的文件或者放入model目录的文件均视为model模块,后者支持多级目录。

举例

// 某server下的model.js,可在service或controller模块中通过server.model获取
module.exports = class {
  constructor({ server }) {
    this.server = server;
  }

  async test () {
    return await this.server.database.redis.getAsync('koa:sess:N1igdxKuU8wWzwe60j9PE5XtLnETToEC');
  }
}

agent

代理模块,用于统一配置外部接口代理并供api模块使用,agent模块默认已集成axios。

以agent命名的文件视为agent模块,不支持目录方式。

举例

// 某server下的agent.js,可在api模块中通过server.agent获取
module.exports = async ({ axios }) => {
  const webapi = axios.create({
    baseURL: 'https://webapi.qingting.fm/api'
  });
  return {
    webapi
  }
}

api

接口模块,用于获取内部或外部接口提供的数据并统一处理提供给service或controller使用。

以api命名的文件或者放入api目录的文件均视为api模块,后者支持多级目录。

举例

// 某server下的api.js,可在service或controller模块中通过server.api获取
module.exports = class {
  constructor ({ server }) {
    this.server = server;
  }
  async homePage  (ctx){
    return this.server.agent.webapi.get('/mobile/homepage');
  }
}

service

服务层模块,用于获取各类数据(model数据、api数据、mock数据),统一进行业务逻辑处理并输出给controller。

以service命名的文件或者放入service目录的文件均视为service模块,后者支持多级目录。

举例

// 某server下的service.js,可在controller模块中通过server.service获取
module.exports = class {
  constructor ({ server }) {
    this.server = server;
  }
  async index  (ctx){
    return await this.server.api.homePage();
  }
}

schedule

定时任务模块,执行定时任务,schedule模块默认已集成node-schedule。

以schedule命名的文件或者放入schedule目录的文件均视为定时任务模块,后者支持多级目录。

可在启动时或运行时使用定时任务。

举例

启动时和运行时执行定时任务,运行时定时任务如果通过接口调用,需做好取消和防重复定时处理

module.exports = class {
  // 启动时执行定时任务
  constructor ({ schedule }) {
    this.schedule = schedule;
    schedule.scheduleJob({ second: 30 }, () => {
      console.log('每分钟第30秒执行');
    });
  }

  // 运行时执行定时任务,可在controller和router模块通过app.schedule或server.schedule获取
  task () {
    this.schedule.scheduleJob({ second: 10 }, () => {
      console.log('每分钟第10秒执行');
    });
  }
}