egg.js踩坑记录(一)开始篇
时间:2022-07-26
本文章向大家介绍egg.js踩坑记录(一)开始篇,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
需求背景
- 中间层与注册中心以及api网关诉求
决策依据
语言决策
- 选型有三个大类(JAVA,GO,nodejs)
- JAVA社区完善场景支撑丰富,劣势前端团队语言瓶颈
- GO性能优势,跨平台先天优势,劣势团队适配性不足(本来应该是最佳选择)
- nodejs团队语言切合度高,劣势性能差,安全性低,环境依赖(依然选择)
框架选择
- 框架选型express(50k+star)和egg.js(10k+star)
- express社区和解决方案优势明细,劣势代码规范,以及企业化的场景支撑都需要从头维护,本人自己在没看egg之前也实现过一个类似的epress模板。有些场景还是有所缺失。
- egg.js优势规范化程度高,场景覆盖比个人想象要全,劣势社区和解决方案支持不太友好,问题都比较难以解决与定位,并不是严格意义上的开箱即用,扩展能力不强。
- 从时间成本和团队规范的角度选择了egg.js
项目细节
场景支撑
- 日志,进程守护,目录规划,配置方案基本不用做了,egg这方面是开箱即用的
规范
- 代码规范
- git规范
{
"lint-staged:js": "npm run lint -- --fix && npm run lint:style",
"lint:prettier": "prettier --check "**/*" --end-of-line auto",
"lint:style": "", "prettier": "prettier -c --write "**/*""
},
"husky": {
"hooks": {
"pre-commit": "npm run lint-staged",
"commit-msg": "commitlint -e $HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js",
"**/*.{js,jsx,tsx,ts,md,json}":
[ "prettier --write" ]
}
- 使用husky和lint-staged解决规范的问题注意事项@commitlint/cli的9.1.2版本存在bug 会出现提交不了的报错,可以选择该版本以下。commitlint配置信息如下
module.exports = { extends: ['@commitlint/config-conventional'],};
中间件加载顺序(应该官方内置的中间件顺序会导致部分功能bug)
- 反向代理中间件需要在bodyParser之前
- graphql中间件又需要bodyParser之后
- 需要自定义启动项的app.js
/*
* @Description: 自定义启动项
* @Author: 吴文周
* @Github: http://gitlab.yzf.net/wuwenzhou
* @Date: 2020-06-28 13:38:19
* @LastEditors: 吴文周
* @LastEditTime: 2020-08-24 22:08:00
*/
'use strict';
const Consul = require('./app/utils/consul');
class AppBootHook {
constructor(app) {
this.app = app;
}
configWillLoad() {
// 此时 config 文件已经被读取并合并,但是还并未生效
// 这是应用层修改配置的最后时机
// 将方向代理服务加载在bodyParser之前
const statusIdx = this.app.config.coreMiddleware.indexOf('bodyParser');
this.app.config.coreMiddleware.splice(statusIdx, 0, 'proxy');
this.app.config.coreMiddleware.splice(statusIdx + 2, 0, 'graphql');
}
async didLoad() {
// 所有的配置已经加载完毕
// 可以用来加载应用自定义的文件,启动自定义的服务
// 例如:创建自定义应用的示例
}
async willReady() {
// 所有的插件都已启动完毕,但是应用整体还未 ready
// 可以做一些数据初始化等操作,这些操作成功才会启动应用
// 例如:从数据库加载数据到内存缓存
}
async didReady() {
// 应用已经启动完毕
}
}
module.exports = AppBootHook;
复制代码
Docker容器化
- docker已经不仅仅是运维考虑的问题,在开发阶段就应该考虑全流程的闭环,环境问题真的很重要在跨团队合作过程中。当然好处不仅仅如此。
- 第一步安装docker(忽略)
- 第二步在项目中添加Dockerfile
# 设置基础镜像,如果本地没有该镜像,会从Docker.io服务器pull镜像
FROM node:alpine
# 设置时区
ENV TZ=Asia/ShanghaiRUN
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 创建app目录
RUN mkdir -p /usr/src/node-app/server
# 设置工作目录
WORKDIR /usr/src/node-app/server
# 拷贝package.json文件到工作目录(被注释的流程会导致依赖无发下载)
# !!重要:package.json需要单独添加。
# Docker在构建镜像的时候,是一层一层构建的,仅当这一层有变化时,重新构建对应的层。
# 如果package.json和源代码一起添加到镜像,则每次修改源码都需要重新安装npm模块,
#这样木有必要。
# 所以,正确的顺序是: 添加package.json;安装npm模块;添加源代码。
# COPY package.json /usr/src/node-app/server/package.json
# 安装npm依赖# 如果使用的境外服务器,即改为`RUN npm i`。
# RUN npm i
# 拷贝所有源代码到工作目录
COPY . /usr/src/node-app/server
# 如果使用的境外服务器,无需使用私有的镜像源,私有仓库下载快,即改为`RUN npm i`。
RUN npm i --registry=xxx
# 暴露容器端口
EXPOSE 7001
# 启动node应用该命令单独配置
CMD npm run docker
- 第三步添加.dockerignore(注意前面有点的)
# Logs
logs
npm-debug.log*
# Coverage directory used by tools like istanbul
coverage
# Dependency directories
node_modules
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
.idea
.node_modules
.vscode
run
typings
- 第四步配置package.json添加执行命令去掉--daemon --title(随意)
"docker": "egg-scripts start",
- 第五步开始docker流程
docker build -t egg .#注意有个.
#启动容器 第一个端口是绑定的本机端口,:后面的端口是egg内部端口对外暴露
docker run -d --name egg -p 9002:7001 egg
- 先查看是否执行成功
docker ps # 是否存在刚才生成的容器
- 如果不存在说明启动失败查看启动日志
docker logs 容器id
- 本机ip+9002即可访问egg的docker服务了
- 其他关键命令
docker images # 查看所有镜像
docker rmi 镜像id或者名称 # 删除镜像
docker rm 容器id或者名称 # 删除容器
完结
撒花
- 提升 Node.js 应用性能的 5 个技巧
- HDUOJ-----1166敌兵布阵
- HDUOJ------2492Ping pong
- HDUOJ----2489 Minimal Ratio Tree
- HDUOJ----2487Ugly Windows
- HDUOJ--------1003 Max Sum
- HDUOJ -----1864 最大报销额(动态规划)
- 行受影响 是什么意思
- c++课程设计(日历)
- 一个程序,让你理解运算符重载操作
- HDUOJ ---1423 Greatest Common Increasing Subsequence(LCS)
- 在运算符重载++,--,+=,-=...
- 排序一栏(总结帖)
- 编程思想 之「异常及错误处理」
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 让小黑窗口听你指挥
- Element表单嵌套数据验证
- 摸鱼的新发现,滚动条无限滚动
- 理解装饰器是怎么使用的
- 第十一节:Activiti6.0——定时器开始事件、消息开始事件和错误开始事件介绍
- linux centos 安装mailx邮件服务器并测试发送一封邮件
- 深入分析Vue-Router原理,彻底看穿前端路由
- linux LVM 一键分区脚本自动扩容
- 再谈构造函数、原型、原型链之间的关系
- Java ConcurrentHashMap 高并发安全实现原理解析
- 第十二节:Activiti6.0——四种边界事件:定时器、错误、信号、补偿
- parted 磁盘分区-挂载-删除-shell脚本进行磁盘分区
- Ubuntu18.04——安装MySQL
- 八种 Vue 组件间通讯方式合集
- Sharding-JDBC 实现分库分表