跳至内容
框架结构
- app[框架主目录]
- controller[控制器]
控制器已实现路由的自动装载,只需要建立具体的控制器. 具体功能业务按需建立目录. 不要将不相干的业务揉在同一模块,同一控制器里.
- admin[业务模块]
- admin.js[控制器]
- system.js[控制器]
- extend[扩展]
扩展目录中,可以给控制器,请求类,上下文扩展通用函数(https://eggjs.org/zh-cn/basics/extend.html)
- io[socket控制器]
特别注意,静态资源,控制器请求以及io请求,都是同一个端口.通过特殊解析实现具体访问.
- controller[socket控制器]
- client[socket模块]
保留模块, 后续新socket编写需要单独建立模块目录,并在具体动作中实现业务逻辑. 同样在egg的基础上补充了自动路由装载的实现.
- client.js[控制器]
这个socket控制器为保留控制器, 为兼容原客户端的socket请求以及回调的特殊处理类. 所有原socket请求都会通过映射, 跳转到/app/service/client/*里的业务类进行特殊处理,并回调.原请求方式. io.emit(‘message’,{api:’login’,param:{username:’xxx’,password:’xxx’}},function(res){})新请求方式. io.emit(‘/admin/admin/login’,{param:{username:’xxx’,password:’xxx’}},function(res){})需要明确注意, socket本质上是不存在回调的. 只是socket.io-client内部和服务器实现了packetid为标志的特殊实现. 其它任何语言都没有…但然. 通过原理编写也行..原理:https://www.cnblogs.com/lightsong/p/10226940.html
- extend[socket扩展]
同/app/extend
- middleware[socket中间件]
- connection.js[连接中间件]
建立链接时, 可以做权限校验
- packet.js[数据包中间件]
数据请求过程中触发
- lib[工具类]
引用方式按最原始的方式引用. 不封装引用的主要目的是保留代码提示.
- common[通用工具目录]
- commonHelper.js[原通用类 ]
按需要加,不需要的不要乱加进来,明确功能的.建立目录单独存放
- expressHelper.js[快递通用类]
快递一些通用的获取调用, 在各自模块中实现, 并提供统一调用. 通用类,根据类型去调用具体的帮助类, 减少过程式代码, 增加代码可读性
- cngg[功能模块目录]
不同于业务, 一般功能模块都有其特殊实现和封装. 单独放这里. 业务功能再在业务目录里实现. 最大限度避免代码混乱. 当扩展达到一定的重复性和可用性, 可以考虑写成插件
- kdn[快递鸟目录]
- …
- middleware[中间件]
个人建议称为中间处理件会相对好理解, 需要先了解下洋葱模型(https://eggjs.org/zh-cn/basics/middleware.html), 类似过滤器
- commonRequest.js[通用请求中间件]
将常规请求进行前置处理, 如get和body合并到ctx.request.params中. 不区分get和post.
- mwAdminUser.js[用户请求权限中间件]
实现用户的权限判断和拦截
- model[数据模型]
暂时使用的数据库是mongodb, 然后暂时选用的访问方式为mongose(https://mongoosejs.com/docs/guide.html), 同时提供原访问方式, 方便快速复用原代码(尽量能写成新的写成新的…别只复制粘贴…)
- Admin[业务模块]
特别注意,其它目录都是小写开头, 只有数据模型的目录和类是大写开头….
- Admin.js[数据模型类]
数据层可复用代码,尽量复用到数据模型. 业务层复用业务模型. 尽量减少重复代码. 如可以写一个函数load(id), 找不到直接报错. 后续通用调用即可.
- public[静态文件]
egg-static提供静态文件访问支持, 同端口访问时. 如果路径为/public/则会自动进入该目录, 客户端和小访问量服务器可以直接使用. 大访问量, 需要实际压力测试看看. 最好还是走nginx做反向代理.
- assets[静态资源目录]
- backstage[后端静态资源目录,主要是组件类封装]
复制原资源文件, 暂时按习惯的来
- upload[上传文件目录]
- router[路由配置]
- schedule[计划任务]
计划任务只需要复制即可使用, 但是发现需要重启服务才会引入, 需要研究下热部署?
- service[业务]
需要理解下新的设计分层, 该形式接近MVC, 但是不是MVC.常规MVC是模型,视图,控制器, egg 结构层是 数据层(model), 控制器(controller), 业务(service), 视图(view), 控制器只做权限以及参数校验, 具体功能封装到业务层中. 主要目的是实现代码的高复用性.如登陆,封装成service.user.login(username,password), 后续任何地方都是调用这个业务, 即可实现登陆. 同时后续的单元测试, 主要是测试业务类.同时, 业务需要以抛出异常的形式代替返回值判断, 并再最外层进行异常处理. 可大大增加代码的可读写以及编写. 避免没必要的各种判断
- admin[业务模块]
- adminService.js[业务类]
结构类似控制器, 全是只为处理具体业务代码
- client[保留模块]
原客户端的io调用使用的方式和egg-socket不一样. 未避免冲突, 单独配置一个io路由,并将原请求动作全部映射到这里的具体业务动作. 同时兼容了socket.io-client的回调
- enterpriseService.js[原客户端所有socket调用]
- view[视图]
所有页面文件以*.ejs做后缀, webstorm,vscode等格式化和开发过程中<% %>会有代码提示, 会极大的提高开发效率, 测试过程中, 也可以考虑页面代码在<%%>中测试再贴回去. 页面保存是实时更新的. nodejs其它功能模块修改在ssd的情况下, 依然需要4,5 秒的重启
- admin[模块目录]
- site[控制器目录]
- login.ejs[登陆页面]
页面对应具体的控制器
- layout[通用页面组件]
- layout.ejs[图层]
包含常用的静态资源文件引入, 控制器里渲染页面时, 图层会包裹具体的页面代码, 可以方便全局性调整. 对于可复用的页面组件, 都可以考虑封装成*.ejs或者作成vue组件, 按需要来
- 200.ejs[通用消息提示页面]
- 500.ejs[通用错误消息提示页面]
- router.js[路由脚本]
用于引用/app/router里的实际路由脚本, 路由脚本在egg的基础上加了自动配置, 只需要复制或新增控制器, 就会自动添加路由
- test[单元测试目录]
- local_test[自己编写的框架外的测试脚本]
- cache[缓存目录]
如果使用缓存, 则目标缓存会生成到该路径下, 如果服务器有多节点. 缓存必需存放到redis或数据库, 不能配置单机的fs或内存缓存. 除非是代码或页面类缓存,视具体情况选择
- config[配置目录]
- locale[翻译目录]
- zh-CN.js[翻译语言配置脚本]
egg-validate的翻译,需要在这个地方进行配置
- config.default.js[默认配置]
- config.dev.js[具体环境配置脚本]
可根据启动命令不同,加载不同配置文件,方便测试
- plugin.js[插件配置]
框架使用插件,必须在这个地方启用, 然后如果有特殊参数配置,在/config/config.default.js里进行详细参数配置. egg默认启用的插件需要到/node_modules/eggjs 里进行查看.
- logs[日志目录]
- test_egg[项目名]
- common-error.log[常规日志]
- egg-agent.log[agent日志]
- egg-schedule.log[计划任务日志]
- egg-web.log[egg内部日志]
- package.json[配置文件]
- 启动命令
- 启动开发环境:npm run dev
- 实际脚本:egg-bin dev –sticky –port 7001
- 启动生产环境:npm run start
- 实际脚本:egg-scripts start –daemon –sticky –port 7001
- 启动模式
- 框架是以 Cluster 方式启动的,而 socket.io 协议实现需要 sticky 特性支持,否则在多进程模式下无法正常工作。
- 注意事项
- 最好指定端口, 否则开发工具崩溃后, 重新运行, 会被重新分配端口, 避免带来不必要的问题
- 框架保留问题, 需要找时间进行优化
- 框架文件过多(超过3w+文件…)
- 重启速度需要再进行研究优化,在ssd的情况下, 重启服务需要大概4,5秒, 较影响开发, 不过配合调试模式, 可以弥补.
- 优化方向:考虑单独写个启动脚本, 抛弃一些特性来实现热更新, 具体再观望看看别人有没有其它实现. 尽可能实现修改后马上可见.
- 页面组件化
之前用nodejs主要还是为了安装一些php实现不了的扩展. 化了一个月的晚上补了下nodejs的基础, 参考了几个框架, 按公司现有的技术栈做的….
总体感觉, 各大公司替换php为nodejs还是有原因的. 合适的地方用合适的工具. 不过egg感觉性能分析有些坑. 这块后面再看看改进.
egg的定位是框架的框架, 自行选择合适自己的积木装出自己要的东西.
目前egg单机热更新方案没有合适的, 由于egg的启动方式不同于pm2, 是多独立的多线程管理. 简单做法是启动两个服务, 然后利用nginx进行平衡. 修改重启时. 依次重启. 实现代码更新的目的. 可以考虑写成一个shell脚本实现重启.