插件开发

任何 Koa 的中间件都可以直接被框架使用。在实际使用场景中,中间件有全局加载(模版渲染中间件)和局部加载(要忽略的路由规则)的需求。针对这种情况,插件形式的中间件有下面两种形式。

初始化插件

通过 uma 命令可以快速的给工程添加插件或者可发布的插件工程

uma plugin init [pluginName]
1

纯中间件形式

比如我们想使用模版渲染中间件 koa-views,就可以通过插件形式,示例如下:

// app/src/plugins/views/index.ts
import * as Koa from 'koa';
import * as views from 'koa-views';

import { Uma } from '@umajs/core';

type TView = {
    root: string
    opts: {
        // views options
    }
};

// options 是插件的配置及 [pluginName].config.ts 的配置结合配置
export default (uma: Uma, options: TView = {}): Koa.Middleware => {
    // uma 实例化对象;options 插件配置的 options,等同于 uma.plugin['view'].options
    return views(options.root, options.opts);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

复合插件形式

export type TPlugin = {
    use?: {
        handler: (ctx: IContext, next?: Function) => any;
    }
    filter?: {
        regexp: RegExp;
        handler: (ctx: IContext, next?: Function) => any;
    };
    ignore?: {
        regexp: RegExp;
        handler: (ctx: IContext, next?: Function) => any;
    };
    method?: {
        type: RequestMethod | RequestMethod[];
        handler: (ctx: IContext, next?: Function) => any;
    };
    results?: { [key: string]: any };
    context?: { [key: string]: any };
    request?: { [key: string]: any };
    response?: { [key: string]: any };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

复合插件形式不仅可以用中间件进行扩展,还可以对我们常用的 Context、Request、Response 进行扩展,扩展之后我们就可以在代码中使用 ctx、req、res 中使用我们扩展的方法。

复合插件形式还提供了use、filter、ignore、method四种局部加载中间件的配置形式,具体配置局部加载规则如下:

  • use 直接使用已有的中间件
  • filter 通过 regexp: RegExp; 属性配置局部加载规则,仅对匹配的规则生效
  • ignore 通过 regexp: RegExp; 属性配置局部加载规则,忽略匹配到的规则
  • method 通过 type: RequestMethod | RequestMethod[]; 属性配置局部加载规则
// plugins/demo.plugin.ts
import { Uma, IContext, TPlugin } from "@umajs/core";

export default (uma: Uma, options: any = {}): TPlugin => {
    return {
        context: {
            test: 123,          // 给 ctx 加上 test
        },
        request: {
            fileName: 'a.png'   // 给 request 加上 fileName
        },
        use: { // 全局加载
            async handler(ctx: IContext, next: Function) {
                console.log(ctx.test, ctx.req.fileName, options);    // >> 123 a.png {}
                console.log('use before');
                await next();
                console.log('use after');
            },
        },
        filter: { // 局部加载 仅对/page/路由生效
            regexp: new RegExp(/page/),
            async handler(ctx: IContext, next: Function) {
                console.log('page get before');
                await next();
                console.log('page get after');
            },
        },
        ignore: { // 局部加载 忽略路由/Page/
            regexp: new RegExp(/page/),
            async handler(ctx: IContext, next: Function) {
                console.log('page ignore before');
                await next();
                console.log('page ignore after');
            },
        },
        method: { // 局部加载 仅对method=GET 生效
            type: 'GET',
            async handler(ctx: IContext, next: Function) {
                console.log('method get before');
                await next();
                console.log('method get after');
            },
        },
    },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

npm 包名规范

欢迎大家在社区中发布支持 Umajs 的插件,为保持插件生态的统一。我们推荐使用umajs-plugin-xxx的命名方式发布自定义的插件包到 npm 中。以方便其他更多人搜索和使用。