FSD (Full Stack Develop) Service - Midway.js 的最佳实践
在这个项目中,你会看到以下基于 Midway 的实践案例 (上层使用 egg.js )
我们正在做以下工程实践例子,大家你遇到什么问题,或者希望追加什么功能,或者学习内部实现。
可以关注我们的仓库(点赞,分享...三连)在 issue 留言,我们会征集你的意见,带来最干货的案例。
帮你扫清学习障碍,让你用起 Midway 来更加得心应手,提升能效,找回编码的乐趣。
所有代码均已经过工程师的测试请放心使用!!!
能力栏目 | 名称 | 进度 |
---|---|---|
概述 | ||
控制器(Controller) | ✓ | |
服务和注入 | ✓ | |
请求、响应和应用 | ✓ | |
Web 中间件 | ✓ | |
启动和部署 | ✓ | |
基础能力 | ||
依赖注入 | ✓ | |
运行环境 | ✓ | |
多环境配置 | ✓ | |
参数校验和转换 | ✓ | |
生命周期 | ✓ | |
使用组件 | ✓ | |
日志 | ✓ | |
本地调试 | ✓ | |
测试 | ✓ | |
增强 | ||
代码流程控制 | ||
方法拦截器(切面) | ||
缓存(Cache)(目前直接使用 Redis) | ✓ | |
Database(TypeORM) | ✓ | |
MongoDB | ||
Swagger | ✓ | |
一体化研发 | ||
开发一体化项目 | ||
非 Serverless 环境使用一体化 | ||
Web技术 | ||
Cookies | ||
Session | ||
跨域 CORS | ✓ | |
微服务 | ||
gRPC | ||
RabbitMQ (生产者) | ✓ | |
RabbitMQ (消费者) | ||
Consul | ||
WebSocket | ||
SocketIO | ||
常用能力 | ||
Admin 登录 | ✓ | |
普通用户登录-账户密码 | ||
OAuth 2.0 | ||
日志监控 | ||
本地上传文件服务 | ||
鉴权中间件 | ✓ | |
接口响应统计中间件 | ✓ | |
统一错误处理 | ✓ | |
SnowFlake 雪花算法生成分布式ID | ✓ | |
Jaeger 链路追踪 | ✓ | |
业务能力 | ||
权限管理 | ✓ | |
角色管理 | ✓ | |
管理员管理 | ✓ | |
菜单管理 | ✓ | |
日志(操作日志,记录管理用户的实际操作) | ✓ |
查看 Midway docs 获取更多信息.
运行该项目需要以下环境支持
- Mysql
- Redis
- Jeager
目前该项目已经集成 Docker 环境,按以下步骤可以自动配置以上依赖。docker-compose 相关文档请查看这里
- 1.确保机器已经安装 Docker。
- 2.在项目目录运行
docker-compose up -d
- 3.停止服务
docker-compose down
如果没有数据库 GUI 工具,可按照下面步骤进行数据库初始化
$ docker ps
// 查看容器ID$ docker exec -it <mysql 容器 ID> /bin/bash
// 进入容器$ mysql shop_development < /data/database/init.sql -uroot -ppassword
// 初始化数据库
先将 database 目录下到 sql 文件迁移到数据库,修改默认的config配置文件
$ npm i
$ npm run dev
$ open http://localhost:7001/
- 使用 Redis 作为用户登录凭证存取的地方
- RTS 收集统计数据 (开发中)
建议使用 Redis 的时候,对所有 key 做好命名空间划分,便于管理。可把 scope 写到对照表中。
借助 jwt 插件做签名校验,管理员的 token 中会包含 id 字段。
所有 admin 相关的缓存数据都放在 admin:xxxx
下面。
admin:accessToken:${id}
缓存管理员 Token 信息admin:userinfo:${id}
缓存管理员基本信息
所有实体表均有 deleted_at 字段(目前基础模块不使用软删除),用于软删除。
如果要关闭软删除,将deletedAt字段注释即可
进行软删除的时候,关系表的数据不做改动。
后期根据需要,用脚本定期清理软删除的数据。
以下模块未使用软删除:
- 权限管理
- 角色管理
- 菜单管理
- 管理员管理
业务软删除单独写一个 BaseModel,其他实体继承该 Model 即可
- 实体查询,继承
BaseModel
的实体会自带软删除判断,例子查看src/app/model/base.ts
- 在做关系查询的时候,关系表需要手动加软删除判断 IS NULL,如下:
/** * 根据菜单id获取数据 * @param id 菜单id */ async getAdminMenuById(id: string) { const row = await this.adminMenuModel .createQueryBuilder() .select() .leftJoinAndSelect( 'AdminMenuModel.roles', 'role', 'role.deletedAt IS NULL' ) .where({ id: id }) .getOne(); return row; }
Jaeger 是 OpenTracing 的一个实现,链路追踪是一个比较复杂的话题,关于 Jaeger 的具体用法请参考它的官方文档
本实现基于 ctx 机制,结合 midway 的依赖注入可实现无侵入式 spanContext 传递
- 默认实现接口级别的采样
- 若需小颗粒度采样,可手动管理 span
ctx.tracerManager.startSpan('SpanName1') await doSomethine() ctx.tracerManager.finishSpan() // 别忘记关闭
做接口响应数据统计的出发点,有两点(即使有类似的第三方包,但还是自己实现以下):
- 帮助排查线上接口响应问题
- 监控系统实时状态
虽然框架本身已经有日志功能,但是很多场景下,我们可能需要看下各个接口服务的响应状态
是在正常服务,还是已经出现问题。在有监控的帮助下,可以快速帮我们定位日志排查问题。
是对应统计实时数据而言,这里我们会使用 RTS 的技术方案,会用到 RabbitMQ 和 Redis
RabbitMQ 作用在于把统计的计算异步化,从而不影响正常的业务请求处理
(消费者的逻辑代码,需要写在单独一个工程,独立部署)
单元测试框架采用 Mocha ,
支持对 case 进行 .skip()
.only()
的随意组合以及快速实现,
适合在包含复杂、耦合的业务项目场景
注意事项:
- 单测文件不支持
nullish
链式操作符,比如assert(res?.body) // 不支持 assert(res && res.body) // 可行
- 配套的前端工程请移步 https://github.com/fsd-nodejs/pc 查看这个项目
- 全栈开发文档以及规范 https://github.com/fsd-nodejs/document 查看这个项目
- midway2.x 深度躺坑记(持续更新)
- 代码提示 好玩的代码提示 by waitingsong (考虑到,每个人对于自定义代码提示的要求不一样,就不合并到参考了,这个PR推荐给大家)
群里会有热心的朋友,也会有新版本发布推送。钉钉扫码加入答疑群
二群
一群(已满)
我们的代码使用 MIT 协议,请放心使用。