基于Egg.js定制业务Web框架(一) - 框架扩展

开发 前端
通过实现扩展Controller,扩展ctx,以及添加默认插件,演示了对Egg.js基本的扩展。当然对于一个完整的业务框架,还缺少很多东西,但以上提供了一种对Egg.js的扩展的思路,希望可以为你扩展提供思路。

[[398340]]

前言

谈到Node.js Web开发,你会想到的是什么?

  • 首先是框架选型:Express、Koa、NestJS、EggJS等,需要从繁多的框架中选择一个适合团队的。
  • 框架选好之后,需要初始化项目,安装依赖、插件、中间件、配置常见库;
  • 假如再一次做新项目,还得从头初始化再来一次。好一点的可以封装一个骨架,从骨架中生成新项目,周而复始。

我们先想想这样做的缺陷是什么?

  • 如果没有骨架,团队成员技术选型不一致,变成遍地开花;每个新项目维护都有学习成本。
  • 即便有骨架,发生一些升级也需要每个项目都统一升级一遍,后续也会导致不统一。

基于以上的原因,我们考虑的解法是:基于通用框架封装一个统一的业务框架,将团队用到的公共功能下沉到业务框架中。

业务框架封装

框架选型

为了选择合适的底层框架,小编整理了awesome-nodejs的仓库(每个分类按github star数排序),从Web框架部分可以看到非常丰富,那么我们如何选择。

awesome-nodejs地址: https://github.com/huaize2020/awesome-nodejs/blob/main/README-zh-CN.md

主流的Web框架选型主要分为两大流派,基于Express 和 基于Koa,他们都是由同一团队打造。Express和Koa在设计思路上的区别在于:

  • Express本身功能内置了很多中间件,集成度高,使用省心,上手即用;
  • Koa使用精简的内核,更轻量,使用需要使用者做技术选型按需搭建积木;

基于以上的设计思路上的差别,基于对灵活配置型的考虑,笔者选择了 基于Koa 的 流派。但他们都太底层,对于搭建企业级业务框架还需要做较多定制。

Egg.js是什么

基于上述的诉求,最后小编选择了Egg.js。

Egg.js地址:https://eggjs.org/zh-cn/

Egg.js是阿里开源的基于Koa2企业级Node.JS框架,其核心设计就是希望基于Egg.js孕育出更多上层框架。

引用官网的一句话

  • 我们深知企业级应用在追求规范和共建的同时,还需要考虑如何平衡不同团队之间的差异,求同存异。所以我们没有选择社区常见框架的大集市模式(集成如数据库、模板引擎、前端框架等功能),而是专注于提供 Web 开发的核心功能和一套灵活可扩展的插件机制。「——官网」

定制目标

在开始定制业务框架前,我们先设定一下需要定制的目标。

  • 扩展Controller,添加API成功/失败返回结果函数;
  • 设置默认模板引擎为 pug;
  • 扩展ctx,添加util, 将dayjs作为统一日期处理库;

编码

如果对Egg.js不太熟悉,建议可以先学习下Egg.js的基本使用。

框架初始化

通过以下命令,初始化项目。其中 --type=framework 表示框架骨架

villa-framework为框架名和项目文件夹名

  1. $ npm init egg --type=framework villa-framework 

以下是初始化出来的目录

  1. villa-framework 
  2. ├── app 
  3. │   ├── extend 
  4. │   └── service 
  5. ├── config 
  6. │   ├── config.default.js 
  7. │   └── plugin.js 
  8. ├── lib 
  9. │   └── framework.js 
  10. ├── test 
  11. │   ├── fixtures 
  12. │   └── framework.test.js 
  13. ├── README.md 
  14. ├── index.js 
  15. └── package.json 

其中app、config目录基本跟正常的Egg.js应用无差异,但增加了framework.js文件,对应用进行扩展。

  1. // lib/framework.js 
  2. 'use strict'
  3.  
  4. const path = require('path'); 
  5. const egg = require('egg'); 
  6. const EGG_PATH = Symbol.for('egg#eggPath'); 
  7.  
  8. class Application extends egg.Application { 
  9.   get [EGG_PATH]() { 
  10.     return path.dirname(__dirname); 
  11.   } 
  12.  
  13. class Agent extends egg.Agent { 
  14.   get [EGG_PATH]() { 
  15.     return path.dirname(__dirname); 
  16.   } 
  17.  
  18. module.exports = Object.assign(egg, { 
  19.   Application, 
  20.   Agent, 
  21. }); 

扩展Controller,添加成功失败返回结果处理函数

  1. // 以下是Egg.js Controller使用的代码 
  2. const Controller = require('egg').Controller; 
  3.  
  4. // 未来修改为 
  5. const Controller = require('villa-framework').Controller; 

由上面源码我们知道,Controller来自egg对象,因此我们只需要替换为我们定义的Controller即可。

  1. // lib/framework.js 增加 
  2. class Controller extends egg.Controller { 
  3.   ok(data) { 
  4.     this.ctx.body = { 
  5.       success: true
  6.       data, 
  7.     }; 
  8.   } 
  9.  
  10.   fail(message, code) { 
  11.     this.ctx.body = { 
  12.       code, 
  13.       message, 
  14.     }; 
  15.   } 
  16.  
  17. // 导出增加Controller 
  18. module.exports = Object.assign(egg, { 
  19.   Application, 
  20.   Agent, 
  21.   Controller, 
  22. }); 

这样用户使用的Controller就变成框架的Controller。

模板引擎设置为 pug

安装依赖

  1. $ npm i --save egg-view-pug 

启动插件

  1. // config/plugin.js 
  2. exports.pug = { 
  3.   enable: true
  4.   package: 'egg-view-pug'
  5. }; 

设置view渲染

  1. // config/config.default.js 
  2. config.view = { 
  3.   mapping: { 
  4.     '.pug''pug'
  5.   }, 
  6. }; 

这样应用框架就不需要再单独安装配置,默认拥有pug模板引擎能力。不同的业务可以根据自己的需求,默认加载并配置一些默认插件。

扩展ctx.util, 将dayjs作为统一日期处理库

安装依赖

  1. $ npm i --save dayjs 

app文件夹中新建util文件,添加day.js并导出

  1. // app/util/dayjs.js 
  2. 'use strict'
  3. const dayjs = require('dayjs'); 
  4. exports.dayjs = dayjs; 

因为新增的util不会默认加载,配置自定义加载器。

  1. // config/config.default.js 
  2. config.customLoader = { 
  3.   // 定义在 app 上的属性名 app.util 
  4.   util: { 
  5.     directory: 'app/util'
  6.     // 如果是 ctx 则使用 loadToContext 
  7.     inject: 'ctx'
  8.     // 是否加载框架和插件的目录 
  9.     loadunit: true
  10.   }, 
  11. }; 

这样框架就会默认加载util。

应用创建

接下来我们创建应用,使用上面的villa-framework

初始化应用

  1. $ npm init egg --type=simple villa-project 
  2. $ npm i --save villa-framework 
  3. $ npm i 
  4. $ npm run dev 

将Egg.js上层框架修改为villa-framework

package.json中egg字段中添加 "framework": "villa-framework"

  1. "egg": { 
  2.   "framework""villa-framework"
  3. }, 

修改controller进行测试

  1. 'use strict'
  2. // app/controller/home.js 
  3. const Controller = require('villa-framework').Controller; 
  4.  
  5. class HomeController extends Controller { 
  6.   async index() { 
  7.     const { dayjs } = this.ctx.util.dayjs; 
  8.     const now = dayjs().format('YYYY-MM-DD HH:mm:ss'); 
  9.     await this.ctx.render('index.pug', { now }); 
  10.   } 
  11.  
  12.   renderOk() { 
  13.     this.ok('hi, egg'); 
  14.   } 
  15.  
  16.   renderFail() { 
  17.     this.fail('fail', 200); 
  18.   } 
  19.  
  20. module.exports = HomeController; 

添加路由

  1. 'use strict'
  2. // app/router.js 
  3. /** 
  4.  * @param {Egg.Application} app - egg application 
  5.  */ 
  6. module.exports = (app) => { 
  7.   const { router, controller } = app; 
  8.   router.get('/', controller.home.index); 
  9.   router.get('/ok', controller.home.renderOk); 
  10.   router.get('/fail', controller.home.renderFail); 
  11. }; 

添加首页模板

在app中创建view文件夹,并添加index.pug

  1. html 
  2.     head 
  3.         title hello world 
  4.     body 
  5.         p hello world 
  6.         p #{now} 

启动后即可看到演示的结果。

打开 http:///127.0.0.1:7001

打开 http:///127.0.0.1:7001/ok

打开 http:///127.0.0.1:7001/fail

总结

以上通过实现扩展Controller,扩展ctx,以及添加默认插件,演示了对Egg.js基本的扩展。

当然对于一个完整的业务框架,还缺少很多东西,但以上提供了一种对Egg.js的扩展的思路,希望可以为你扩展提供思路。

当前系列作为《基于Egg.js定制业务Web框架》系列一, 后续将持续输出:定制IoC容器,定制注解系统、monorepo改造、框架CLI系列,敬请关注。

框架地址:https://github.com/huaize2020/blog/tree/main/projects/villa-v1/villa-framework

应用调用地址:https://github.com/huaize2020/blog/tree/main/projects/villa-v1/villa-project

awesome-nodejs: https://github.com/huaize2020/awesome-nodejs/blob/main/README-zh-CN.md

 

责任编辑:姜华 来源: Eval Studio
相关推荐

2024-03-14 08:32:37

HTMLWeb 框架PPT

2010-03-29 13:37:15

ibmdwJAXB

2024-03-11 10:19:30

Plasmo浏览器Web

2019-08-29 10:58:02

Web 开发框架

2023-11-03 08:04:47

Web微前端框架

2012-03-07 14:32:41

Node.js

2009-11-12 16:17:13

.NET

2009-06-25 17:14:59

JSF框架

2012-09-26 09:46:29

ASP.NETWeb框架

2010-08-10 14:53:32

FlexRiawave

2010-08-05 13:50:54

Flex框架

2010-08-13 14:29:45

Flex框架

2023-04-27 08:23:38

JavaScriptVue.jsMVVC

2009-03-17 09:15:20

图表框架CSSJavaScript

2017-07-18 15:13:17

2009-06-19 09:52:46

Acegi安全框架Spring框架

2012-02-08 13:49:53

Node.js

2021-07-15 11:16:31

Spring WebWebFlux架构

2022-05-30 09:32:07

Spring容器

2009-03-16 09:16:13

行为扩展WCF.NET
点赞
收藏

51CTO技术栈公众号