当前位置: 首页 > 后端技术 > Node.js

EggBorn.js:顶级Javascript全栈开发框架

时间:2023-04-03 20:48:14 Node.js

什么是EggBorn.jsEggBorn.js是顶级Javascript全栈开发框架。EggBorn.js是使用Javascript进行全栈开发的最佳实践。EggBorn.js没有重新发明轮子,而是采用了业界最新的开源技术,全栈开发的最佳组合。EggBorn.js前端使用Vue.js+Framework7/VueRouter+Webpack,后端使用Koa.js+Egg.js,数据库使用mysql。EggBorn.js紧跟开源技术的最新成果,持续优化,让整个框架时刻保持在最佳状态。EggBorn.js重点解决什么问题:业务模块化Javascript技术的蓬勃发展,为前后端开发带来了更流畅的体验,显着提升了开发效率。但是,仍然有网友质疑Javascript是否能胜任大型Web应用的开发。大型Web应用的特点是随着业务的增长,需要开发大量的页面组件。面对这种场景,一般有两种解决方案:1.使用单页面的构建方式,缺点是生成的部署包非常大。2使用异步页面加载方式,缺点是页面过于碎片化,需要和后台频繁交互。EggBorn.js实现了第三种方案:将3个页面组件按照业务需求进行分类,模块化,实现了模块的异步加载机制,从而弥补了前两种方案的不足,完美满足了大型Web应用业务不断增长的需求.EggBorn.js的技术特点业务模块化:页面组件按模块组织加载方式灵活:模块可以异步加载,也可以同步加载模块内聚性强:模块包括前端页面组件和后端业务逻辑参数配置灵活:在模块中模块前后端可单独进行参数配置国际化:模块内前后端支持独立国际化模块隔离:页面、数据、逻辑、路由、配置等元素模块的全部命名空间隔离,避免模块间的变量污染和冲突超简单易用的事务处理:只需在路由记录上配置一个参数,即可完美实现数据库的事务处理。渐进式开发:由于模块的高内聚性,业务可以以模块的形式沉淀,在多个项目中复用。可以贡献到npm开源社区,也可以部署到公司内部私有npm仓库。使用EggBorn.js,不仅可以复用组件,还可以复用业务模块。快速安装EggBorn.js脚手架$npminstall-gegg-born新建项目$egg-bornproject_name$cdproject_name$npminstallEggBorn.js目前提供2个项目脚手架,分别是front-backend-mysql--前后端全栈项目templatefront--前端项目模板,后端可以使用其他方案配置mysql连接参数。如果使用front-backend-mysql模板,请配置mysql连接参数(空数据库即可)编辑src/backend/config/config。default.js文件//mysqlconfig.mysql={clients:{//不要更改名称__ebdb:{host:'127.0.0.1',port:'3306',user:'travis',password:'',database:'卵生',},},};运行项目启动后端服务$npmrundev:backend启动前端服务$npmrundev:frontEggBorn.js架构图系统架构项目文件结构模块文件结构模块开发命名规范为了不断积累业务模块和为了达到高度可复用的效果,所有模块的命名空间必须完全隔离,避免相互污染和冲突,所以采用如下命名方式:egg-born-module-{providerId}-{moduleName}如moduleegg-born-module-a-version,各链接命名信息如下:providerId:amoduleName:versionfullName:egg-born-module-a-versionrelativeName:a-version前端页面路由地址:/a/version/{page}后端API路由地址:/a/version/{controller}/{action}加载机制模块支持异步加载和同步加载。默认是异步加载。如果要同步加载,只需要在模块名后面加上-sync后缀即可,比如模块egg-born-module-aa-login-sync。新建一个模块,进入src/module目录执行脚手架,创建模块文件skeleton$egg-bornmodule_relative_nameEggBorn.js目前提供2种模块脚手架,即module--全栈模块模板module-front--front-endmoduletemplatemodule前端开发前端页面路由在front/src/routes.js中添加页面路由,比如functionload(name){returnrequire(`./pages/${name}.vue`).default;}exportdefault[{path:'welcome/:who',component:load('welcome')},{path:'profile',component:load('profile'),meta:{requiresAuth:true}},{path:'/login',component:load('login')},];path:路径,支持参数。以/开头代表根页面组件。登录页面组件通常是这样配置的组件:页面组件对象meta:路由元数据meta.requiresAuth:如果页面组件需要登录,必须设置为true才能在页面中引用该页面组件,请使用一个绝对路径,如前端状态管理Vuex是专门为Vue.js应用开发的状态管理模式。EggBorn.js使用Vuex实现了完全隔离的模块状态管理机制。在front/src/store.js中添加state,比如exportdefaultfunction(Vue){return{state:{message:'helloworld',},};}在页面组件中访问这个模块stateconstmessage=this.$local.state.message;访问页面组件中的其他模块状态constmessage=this.$store.state[providerId][moduleName].message;更多信息请参考:Vuex前端参数配置在front/src/config中添加配置信息在/config.js中,如exportdefault{mode:1,};页面组件中只支持访问本模块内部的参数配置constmode=this.$config.mode;前端国际化在front/src/config/locale目录下添加国际化文件。zh-cn.js文件中的语言定义示例如下exportdefault{mode:'mode',"Helloworld!I'm%s.":'Hello,world!我是%s。',};国际化语言采用全局合并的方式,有利于语言资源的共享。页面组件中的访问方式如下模块后端开发后端api路由在backend/src/routes.js中添加api路由,如consthome=require('./controller/home.js');module.exports=[{method:'get',path:'home/index',controller:home,action:'index',transaction:true},];method:get/post等方法path:path,支持参数component:Controllerobjectaction:Controllermethod,如果不设置,路径末尾的单词会自动使用transaction:默认为false,如果设置为true,会启用数据库事务访问模块apiroutethis.$在前端页面组件api.get('home/index').then(data=>{}).catch(err=>{});访问其他模块api路由this.$api.get('/providerId/moduleName/home/index').then(data=>{}).catch(err=>{});BackendControllerbackendController的实现和Egg.js一致module.exports=app=>{classHomeControllerextendsapp.Controller{asyncindex(){constmessage=awaitthis.service.home.index();this.ctx.success(消息);}}返回HomeController;};有关更多信息,请参阅:鸡蛋。js控制器后端ServiceService用于封装业务逻辑,被Controller调用。实现方式和Egg.js一致module.exports=app=>{classHomeextendsapp.Service{asyncindex(){constres=awaitthis.ctx.db.queryOne('showtables');返回资源;}}返回首页;};与Egg.js不同的是,Service使用ctx.db来操作数据库,从而自动支持数据库事务。更多信息请参考:Egg.jsServiceBackendController调用为了支持大型web系统的开发,EggBorn.js支持模块后端Controller之间的调用,例如constmessage=awaitthis.ctx.performAction({method:'get',url:'home/index',query:{username:'kevin',},params:{mode:1,},body:{content:'ready',},});method:get/post等方法url:使用相对路径访问本模块的Controller,使用/开头的绝对路径访问其他模块的Controller。query,params,body:与常规Controller参数一致。后端数据库操作与Egg.js一致更多信息请参考:Egg.jsMySQL后端数据库事务EggBorn.js提供了更多便利数据库事务的实现方式是在后端api路由记录中配置事务参数,以及该服务使用ctx.db来操作数据库。如果主Controller通过ctx.performAction调用子Controller,数据库事务开启规则如下:主Controller配置子Controller配置子Controller实际启用truetruetruetruefalsettruefalsetruetruefalsefalse后端参数配置在backend/添加配置信息src/config/config.js,如module.exports=appInfo=>{constconfig={};config.message="Helloworld!我是%s。";返回配置;};访问本模块内部参数的配置示例如下constmessage=this.ctx。配置信息;后端国际化在backend/src/config/locale目录下添加国际化文件。zh-cn.js文件中的语言定义示例如下module.exports={"Helloworld!I'm%s.":'Hello,world!我是%s。','未找到':'未找到',};国际化语言采用全局合并的方式,有利于语言资源的共享。访问方法如下后端错误处理在backend/src/config/errors.js文件中添加错误码//错误码应该从1001module.exports={1001:'notfound',};返回错误信息的例子如下this.ctx.fail(1001);也可以抛出异常的例子如下this.ctx.throw(1001);模块管理模块依赖于EggBorn。js通过package.json文件管理模块依赖。例如,模块aa-module1依赖于aa-module2,需要在模块aa-module1的package.json文件中做如下配置{"name":"egg-born-module-aa-module1","version":"0.0.1","eggBornModule":{"dependencies":{"aa-module2":"0.0.1"}},"dependencies":{"egg-born-module-aa-module2":"^0.0.1"}}设置"egg-born-module-aa-module2":"^0.0.1"是在安装模块aa-module1时自动安装模块aa-module2。如果模块未公开发布,则不必设置。模块数据版本模块一般需要操作数据库。当模板版本升级时,数据库结构也可能发生变化。EggBorn.js实现模块数据版本管理,方便业务模块的积累。在模块的package.json文件中配置fileVersion为当前数据版本{"name":"egg-born-module-aa-module1","version":"0.0.1","eggBornModule":{"fileVersion":1}}在模块后端添加Api路由{method:'post',path:'version/update',controller:version}添加版本Controllermodule.exports=app=>{classVersionControllerextendsapp.Controller{asyncupdate(){awaitthis.service.version.update(this.ctx.getInt('version'));这个.ctx.成功();}}返回VersionController;};添加版本Servicemodule.exports=app=>{classVersionextendsapp.Service{asyncupdate(version){if(version===1){//dosomething}}}returnVersion;};在启动后端服务时,EggBorn.js会自动检测模块数据版本的变化,并执行相应的路由完成数据的版本升级。模块发布当项目中的模块代码稳定后,模块可以公开发布,贡献给开源社区。也可以在公司内部建立一个npm私有仓库,然后将模块发布到私有仓库,形成公司资产,方便复用。模块发布步骤如下$cdpath/to/module--进入模块目录$npminstall--安装模块依赖$npmrunbuild:front--构建前端代码$npmrunbuild:backend--构建后端代码$npmpublish--发布到npm仓库测试驱动目前只支持后端测试驱动backendControllertest在backend/test/controller目录下添加Controller测试文件//controller/home.test.jsconst{app,模拟,断言}=require('egg-mock/bootstrap');constparseMockUrl=function(url){constprefix=app.mockUtil.parseUrlFromPackage(__dirname);return`${prefix}${url}`;};describe('test/controller/home.test.js',()=>{it('action:index',async()=>{constresult=awaitapp.httpRequest().get(parseMockUrl('home/index'));assert(result.body.code===0);});});后端服务测试在backend/test/service目录下添加服务测试文件//service/home.test.jsconst{app,mock,assert}=require('egg-mock/bootstrap');constparseMockUrl=function(){returnapp.mockUtil.parseUrlFromPackage(__dirname);};describe('test/service/home.test.js',()=>{it('index',async()=>{constctx=app.mockContext({mockUrl:parseMockUrl()});constmessage=awaitctx.service.home.index();断言(消息);});});在项目根目录下执行测试执行测试$npmruntest:backend$npmruncov:backend前端架构配置前端启动文件前端架构提供两种方案Vue.js+Framework7Vue.js+VueRouterFramework7是一个移动开发专属的UI界面库,内置路由机制VueRouter是Vue.js的官方路由库,VueRouter可以和其他各种UI界面库一起使用。在src/front/main.js文件中切换//选择一个//framework7importmainfrom'./framework7/main.js';//vuerouter//importmainfrom'./vuerouter/main.js';//exportexport默认main;前端参数配置src/front/config/config.js文件中的参数配置可以覆盖模块参数exportdefault{module:{'aa-hello':{mode:2,},},};前端国际化在src/front/config/locale目录下添加一个国际化文件,可以覆盖模块的国际化语言。zh-cn.js文件中的语言定义示例如下exportdefault{mode:'mode',};后端架构配置后端架构后端架构基于Egg.js,全面支持Egg.js提供的所有功能和特性。更多信息请参考:Egg.js后端参数配置src/backend/config/config.default.js文件参数配置可以覆盖模块参数module.exports=appInfo=>{constconfig={};//模块配置config.module={'aa-hello':{mode:2,},};返回配置;};后端国际化在src/backend/config/locale目录下添加一个国际化文件,可以覆盖模块的国际化语言。zh-cn.js文件中的语言定义示例如下停止后端服务$npmrunstop:backend后端服务启动参数配置editbuild/config.js文件//backendconstbackend={port:7002,hostname:'127.0.0.1',};nginx配置强烈推荐使用nginx来托管前端静态资源和反向代理后端服务。配置如下:server{listen80;服务器名称example.comwww.example.com;设置$node_port7002;根/路径/到/www;location/api/{proxy_http_version1.1;proxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_set_header主机$http_host;proxy_set_headerX-NginX-Proxytrue;proxy_set_header升级$http_upgrade;//127.0.0.1:$node_port$request_uri;proxy_redirect关闭;如果你对GitHub贡献有任何疑问,请提交issue,或者直接修改提交PR!