nocobase/docs/guide/plugin-development/index.md
chenos ca7af9c8cc
feat: new version of the documentation (#95)
* feat: new version of the documentation

* feat: add English catalog translation

* Update quickstart.md

* Update quickstart.zh-CN.md

* Update quickstart.zh-CN.md

* Update quickstart.zh-CN.md

* Update quickstart.zh-CN.md

* feat: update quickstart

* update doc

* update pepository api doc

Co-authored-by: ChengLei Shao <chareice@live.com>
2021-10-28 22:55:51 +08:00

2.9 KiB
Raw Blame History

order toc group
1 menu
title path order
Plugin Development /guide/plugin-development 5

What is a Plugin?

插件是按功能划分的可插拔的独立模块。

Why Write Plugins?

NocoBase 提供了丰富的 API 用于应用开发,即使不写插件也是可以实现功能扩展。之所以写成插件,是为了降低耦合,以及更好的复用。做到一处编写,随处使用。当然有些业务联系非常紧密,也没有必要过分的插件化拆分。

How to Write a Plugin?

例如,添加一个 ratelimit 中间件,可以这样写:

import ratelimit from 'koa-ratelimit';

app.use(ratelimit({
  driver: 'memory',
  db: new Map(),
  duration: 60000,
  errorMessage: 'Sometimes You Just Have to Slow Down.',
  id: (ctx) => ctx.ip,
  headers: {
    remaining: 'Rate-Limit-Remaining',
    reset: 'Rate-Limit-Reset',
    total: 'Rate-Limit-Total'
  },
  max: 100,
  disableHeader: false,
  whitelist: (ctx) => {
    // some logic that returns a boolean
  },
  blacklist: (ctx) => {
    // some logic that returns a boolean
  }
}));

但是这种写法只能开发处理不能动态移除。为此NocoBase 提供了可插拔的 app.plugin() 接口,用于实现中间件的添加和移除。改造之后,代码如下:

import ratelimit from 'koa-ratelimit';

class RateLimitPlugin extends Plugin {
  constructor(options) {
    super(options);
    this.ratelimit = ratelimit(options.options);
  }

  enable() {
    this.app.use(this.ratelimit)
  }

  disable() {
    this.app.unuse(this.ratelimit);
  }
}

app.plugin(RateLimitPlugin, {
  name: 'rate-limit',
  version: '1.0.0',
  options: {
    driver: 'memory',
    db: new Map(),
    duration: 60000,
    errorMessage: 'Sometimes You Just Have to Slow Down.',
    id: (ctx) => ctx.ip,
    headers: {
      remaining: 'Rate-Limit-Remaining',
      reset: 'Rate-Limit-Reset',
      total: 'Rate-Limit-Total'
    },
    max: 100,
    disableHeader: false,
    whitelist: (ctx) => {
      // some logic that returns a boolean
    },
    blacklist: (ctx) => {
      // some logic that returns a boolean
    }
  }
});
  • 将 ratelimit 的参数提炼出来,更进一步可以把参数配置交给插件管理面板
  • 当插件激活时,执行 plugin.enable(),把 ratelimit 添加进来
  • 当插件禁用时,执行 plugin.disable(),把 ratelimit 移除

以上就是插件的核心内容了,任何功能扩展都可以这样处理。只要两步:

  • 实现插件的 enable 接口,用于添加功能;
  • 再实现 disable 接口,用于移除功能模块。
class MyPlugin extends Plugin {
  enable() {
    // 添加的逻辑
  }

  disable() {
    // 移除的逻辑
  }
}

不实现 disable 可不可以?

disable 接口是为了实现插件的热插拔,应用不需要重启就能实现插件的激活和禁用。如果某个插件不需要被禁用,也可以只实现 enable 接口。