当前位置: 首页 > 科技观察

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

时间:2023-03-17 23:43:08 科技观察

前言说到Node.jsweb开发,你会想到什么?首先是框架的选择:Express、Koa、NestJS、EggJS等。从适合您团队的各种框架中进行选择。框架选好后,需要初始化项目,安装依赖、插件、中间件,配置常用库;如果你再做一个新项目,你必须从头开始重新初始化它。更好的可以封装一个骨架,从骨架生成一个新的项目,周而复始。我们先想想这样做有什么缺陷?没有骨架,团队成员的技术选择不一致,就会遍地开花;每个新项目的维护都有学习成本。即使有骨架,有些升级需要每个项目统一升级,这样会导致以后不一致。基于以上原因,我们考虑的方案是:在通用框架的基础上封装一个统一的业务框架,将团队使用的公共功能下沉到业务框架中。业务框架封装框架选择为了选择合适的底层框架,小编整理了awesome-nodejs的仓库(每个分类按照githubstar数排序)。从webframework部分可以看出非常丰富,那么我们该如何选择呢。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为框架名和项目文件夹名$npminitegg--type=frameworkvilla-framework下面是初始化目录villa-framework├──app│├──extend│└──service├──config│├──config.default.js│└──plugin.js├──lib└└──framework.js├──test│├──fixtures│└──framework.test.js├──README.md├──index.js└──package.jsonapp和config目录与普通的Egg.js应用基本相同,只是增加了framework.js文件来扩展应用。//lib/framework.js'usestrict';constpath=require('path');constegg=require('egg');constEGG_PATH=Symbol.for('egg#eggPath');classApplicationextendsegg.Application{get[EGG_PATH](){returnpath.dirname(__dirname);}}classAgentextendsegg.Agent{get[EGG_PATH](){returnpath.dirname(__dirname);}}module.exports=Object.assign(egg,{Application,Agent,});扩展Controller,增加一个成功或失败返回结果处理函数//下面是Egg.jsController使用的代码constController=require('egg').Controller;//以后修改为constController=require('villa-框架”)。控制器;通过上面的源码我们知道Controller来自于egg对象,所以我们只需要将其替换为我们定义的Controller即可。//lib/framework.js添加classControllerextendsegg.Controller{ok(data){this.ctx.body={success:true,data,};}fail(message,code){this.ctx.body={code,message,};}}//添加Controllermodule.exports=Object.assign(egg,{Application,Agent,Controller,});使得用户使用的Controller成为框架的Controller。模板引擎设置为pug安装依赖$npmi--saveegg-view-pug启动插件//config/plugin.jsexports.pug={enable:true,package:'egg-view-pug',};设置视图渲染//config/config.default.jsconfig.view={mapping:{'.pug':'pug',},};这样应用框架不需要单独安装和配置,默认具备pug模板引擎能力。不同的业务可以根据自己的需要默认加载和配置一些默认插件。扩展ctx.util,将dayjs作为统一的日期处理库安装并依赖$npmi--savedayjsapp文件夹新建util文件,添加day.js并导出//app/util/dayjs.js'usestrict';constdayjs=require('dayjs');exports.dayjs=dayjs;因为默认情况下不会加载新的util,所以配置一个自定义加载器。//config/config.default.jsconfig.customLoader={//app上定义的属性名app.utilutil:{directory:'app/util',//如果是ctx,使用loadToContextinject:'ctx',//是否加载框架和插件的目录loadunit:true,},};这样框架就会默认加载util。应用创建接下来我们创建一个应用,使用上面的villa-framework初始化应用$npminitegg--type=simplevilla-project$npmi--savevilla-framework$npmi$npmrundev修改Egg.js的上层框架为villa-frameworkpackage.jsonegg字段添加"framework":"villa-framework""egg":{"framework":"villa-framework",},修改controller测试'usestrict';//app/controller/home.jsconstController=require('villa-framework').Controller;classHomeControllerextendsController{asyncindex(){const{dayjs}=this.ctx.util.dayjs;constnow=dayjs().format('YYYY-MM-DDHH:mm:ss');awaitthis.ctx.render('index.pug',{now});}renderOk(){this.ok('hi,egg');}renderFail(){this.fail('fail',200);}}module.exports=HomeController;添加路由'usestrict';//app/router.js/***@param{Egg.Application}app-eggapplication*/module.exports=(app)=>{const{router,controller}=app;router.get('/',controller.home.index);router.get('/ok',controller.home.renderOk);router.get('/失败',controller.home.renderFail);};添加首页模板在app中创建view文件夹,添加index.pughtmlheadtitlehelloworldbodyphelloworldp#{now}启动后可以看到演示结果打开http:///127.0.0.1:7001打开http:///127.0.0.1:7001/ok打开http:///127.0.0.1:7001/失败总结上面通过实现扩展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-projectawesome-nodejs:https://github.com/huaize2020/awesome-nodejs/blob/main/README-zh-CN.md