课程名称:web前端架构师
课程章节:第14周 第三章、第四章
主讲老师:张轩
课程内容: eggjs 插件和中间键
相关文档地址。https://www.eggjs.org/zh-CN/basics/plugin
egg 插件列表 https://github.com/search?q=topic%3Aegg-plugin&type=Repositories
插件机制 是egg 的一大特色。它不但可以保证框架核心的足够精简、稳定、高效,还可以促进业务逻辑的复用,生态圈的形成。
我们在使用 Koa 中间件过程中发现了下面一些问题:
综上所述,我们需要一套更加强大的机制,来管理、编排那些相对独立的业务逻辑。
比如我们要使用 ejs 模版渲染插件
npm i egg-plugin-ejs
在 config/plugin.ts 添加
const plugin: EggPlugin = { ejs: { enable: true, package: 'egg-view-ejs', }, };
修改 config/config.default.ts
config.view = { mapping: { '.ejs': 'ejs', }, };
编写 view 文件
// app/view/dog.ejs <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><%=title%></title> </head> <body> <img src="<%=url%>"/> </body> </html>
修改 controller
import { Controller } from 'egg'; export default class DogController extends Controller { async dog() { const { service, ctx } = this; const res = await service.dog.show<{ message: string status: string }>(); // 渲染 eje 文件 await ctx.render('dog.ejs', { url: res.message, title: 'Dog', }); } }
中间键放在 app/middleware 目录下
新建一个文件logger.ts
import { Context } from 'egg'; import { appendFileSync } from 'fs'; export default () => { return async (ctx: Context, next: () => Promise<any>) => { const startTime = Date.now(); await next(); appendFileSync('./log.txt', `time: ${Date.now() - startTime} ms -- url:${ctx.url}\n`); }; };
然后在 config.default.ts 中配置
config.middleware = [ 'logger' ];
中间件和 Koa 的中间件写法是一模一样的,所以任何 Koa 的中间件都可以直接被框架使用。
首先需要修改中间键的名称,因为上面写的 logger 与 eggjs 自带的中间键同名会发生冲突
修改 logger.ts 为 myLogger.ts.
然后修改 config.default.ts
const bizConfig = { ... // 表示 myLogger 中间键需要传递的参数 myLogger: { allowedMethod: [ 'POST' ], }, };
在 中间键中接受参数
// options 就是中间键接受的参数对象 export default (options: any) => { return async (ctx: Context, next: () => Promise<any>) => { const startTime = Date.now(); await next(); if (options.allowedMethod.includes(ctx.method)) { appendFileSync('./log.txt', `time: ${Date.now() - startTime} ms -- url:${ctx.url}, method: ${ctx.method}\n`); } }; };
middleware 在特定的路由上使用也是可以的, 中间键会挂载到 app 对象上,因此我们可以在很多地方都可以使用中间键
import { Service } from 'egg'; export default class DogService extends Service { async show<T>() { this.app.middleware.myLogger const res = await this.ctx.curl<T>('https://dog.ceo/api/breeds/image/random', { dataType: 'json', }); return res.data; } }