引言
学习课程来自于抖音“哲玄前端”课程(《大前端全栈实践课》),从零开始做一个企业级的全栈应用框架。
一、elpis-core整体架构设计
elpis-core
是基于koa
实现的类似于egg
的轻量化服务端。通过koa
实例,将各种loader
文件进行解析并加载到内存中。
1. BFF
BFF架构设计
BFF(Backend For Frontend)中间层,一种架构设计,主要用于解决前后端数据协作及微服务框架的数据聚合问题。
(1). 接入层
-
router-schema
基于json-schema
及ajv
校验器,对请求头(headers
),请求体(params/body/query
)进行合法校验。
-
router
基于koa-router
实现动态路由分发,支持 API 与页面路由,具备分组管理与中间件绑定能力。
-
middleware
请求处理管线,采用洋葱圈模型,支持全局或特定 API 配置,可实现签名验证、参数校验、异常处理等功能。
(2). 业务层
-
env
管理环境变量,自动识别NODE_ENV
,默认本地(local
)。
-
config
多环境配置,通过配置config.{env}.js
,提取各环境变量。
-
extend
全局功能(插件/工具)拓展,直接挂载至app
实例上。(类似于日志等)
-
controller
封装基类,处理具体逻辑,整合参数
(3). 服务层
-
service
封装数据库读写与外部服务调用,为controller
提供原子化数据操作接口。
2. 洋葱圈模型
洋葱圈模型
基于Koa
的洋葱模型,每个请求都会经过一系列中间件处理,形成一个完整的处理管道。这种设计使得横切关注点(如日志、错误处理、参数校验)能够优雅地实现。
二、设计原则(思想)
elpis-core
遵循的原则(思想)是约定大于配置,有清晰的目录结构,按照一套统一的约定开发模式。同时采用模块化的设计,每个模块责任单一,互相独立,方便维护和扩展。
elpis
|-- app // 文件目录
| |-- controller // 业务逻辑处理
| |-- extend // 全局拓展
| |-- middleware // 中间件
| |-- public // 静态资源
| |-- router // 路由
| |-- router-schema // 路由校验规则
| |-- service // api及数据处理
| |-- middlewares.js // 全局中间件
|-- config // 环境配置文件
| |-- -config.beta.js //测试环境
| |-- -config.default.js //默认环境
| |-- -config.local.js //本地环境
| |-- -config.prod.js //生产环境
|-- elpis-core // 引擎内核
| |-- loader
| | |-- config
| | |-- controller
| | |-- extend
| | |-- middleware
| | |-- router-schema
| | |-- router
| | |-- service
| |-- env.js //环境获取
| |-- index.js
|-- index.js // 入口文件
三、 elpis-core的设计实现
1.加载器功能
通过index.js
读取、解析、加载各个目录下的loader文件,并挂载到koa实例的对应属性上,实现将文件转化为内存(运行时)
const Koa = require("koa");
const path = require("path");
const { sep } = path; //兼容不同操作系统上的斜杠
const env = require("./env");
const middlewareLoader = require("./loader/middleware");
const routerSchemaLoader = require("./loader/router-schema");
const routerLoader = require("./loader/router");
const controllerLoader = require("./loader/controller");
const serviceLoader = require("./loader/service");
const configLoader = require("./loader/config");
const extendLoader = require("./loader/extend");
module.exports = {
/**
* 启动项目
* @params options 项目配置
* options = {
* name // 项目名称
* homePage // 项目首页
* }
*/
start(options = {}) {
//koa实例
const app = new Koa();
//应用配置
app.options = options;
//基础路径
app.baseDir = process.cwd();
//业务路径
app.businessPath = path.resolve(app.baseDir, `.${sep}app`);
//初始化环境配置
app.env = env();
//加载middleware
middlewareLoader(app);
console.log(`--[start] load midlleware done --`);
//加载routerSchema
routerSchemaLoader(app);
console.log(`--[start] load routerSchema done --`);
//加载controller
controllerLoader(app);
console.log(`--[start] load controller done --`);
//加载service
serviceLoader(app);
console.log(`--[start] load servic done --`);
//加载config
configLoader(app);
console.log(`--[start] load config done --`);
//加载extend
extendLoader(app);
console.log(`--[start] load extend done --`);
//注册全局中间件
try {
require(`${app.businessPath}${sep}middleware.js`)(app);
console.log(`--[start] load golbal middleware done --`);
} catch (e) {
console.log("[exception] there is no golbal middleware file.");
}
//加载router
routerLoader(app);
console.log(`--[start] load router done --`);
//启动服务
try {
const port = process.env.PORT || 8080;
const host = process.env.Ip || "0.0.0.0";
app.listen(port, host);
console.log(`Server running on port: ${port}`);
} catch (e) {
console.log(e);
}
},
};
2.加载器顺序
通过 Loader 的加载顺序管理模块生命周期
-
环境配置加载
-
加载基础服务
- 中间件
- 路由检验规则
- 服务
- 控制器
- 拓展功能
-
注册全局中间件
-
注册路由
-
启动应用
3.页面渲染
通过koa-nunjucks-2,提供的一个render函数,对页面进行渲染
扩展
1、koa:
Koa | Koa(koajs)中文文档 | Koa(koajs)中文网
Koa 使用Promise和异步功能来摆脱回调地狱的应用程序,并简化错误处理。 它暴露了自己的ctx.request和ctx.response对象,而不是 node 的req和res对象。
2、koa-bodyparser
koa-bodyparser是一个用于 Koa 框架的中间件,用于解析 HTTP 请求的主体(body)。它支持解析 JSON、表单(form)和文本(text)类型的主体,但不支持解析 multipart 格式的数据。
3、ghooks
package.json内配置
"scripts": {
"lint": "eslint --quiet --ext js,vue .",
"test": "_ENV='local' mocha test/**/*.js"
},
"config": {
"ghooks": {
"commit-msg": "validate-commit-msg",
"pre-commit": "npm run lint"
}
}
4、log4js(日志工具)
log4js是一个流行的Node.js日志记录库
5、json-schema/Ajv
JSON Schema 是用于验证 JSON 数据结构的强大工具,Schema可以理解为模式或者规则
Ajv 是一个用于 JavaScript 应用的安全性和可靠性的 JSON 结构校验器
通过 json-schema 和 ajv 对API规则进行约束,配合api-params-verify中间件使用
schemas.headers.$schema = $schema
validate = ajv.compile(schemas.headers)
vaild = validate(headers)
6、koa-nunjucks-2
用来作为模板引擎,为 koa 应用提供页面渲染功能
默认会在请求上下文(context)上增加render()
方法,通过调用ctx.render('模板名', 数据)
就可以渲染页面
const koaNunjucks = require('koa-nunjucks-2');
app.use(koaNunjucks({
ext: 'tpl',
path: path.resolve(process.cwd(), './app/public'),
nunjucksConfig: {
trimBlocks: true,
noCache: true
}
})
);