2021-10-28 14:55:51 +00:00
---
order: 1
toc: menu
group:
title: Plugin Development
path: /guide/plugin-development
order: 5
---
# What is a Plugin?
2021-10-31 01:44:52 +00:00
Plugins are pluggable, standalone modules divided by function.
2021-10-28 14:55:51 +00:00
## Why Write Plugins?
2021-10-31 01:44:52 +00:00
NocoBase provides a rich API for application development and can be extended even without writing plugins. The reason for writing plugins is to reduce coupling and better reuse. To do a place to write, use anywhere. Of course, some business links are very close, there is no need to overly plug-in split.
2021-10-28 14:55:51 +00:00
## How to Write a Plugin?
2021-10-31 01:44:52 +00:00
For example, to add a ratelimit middleware, you can write it like this.
2021-10-28 14:55:51 +00:00
```ts
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
}
}));
```
2021-10-31 01:44:52 +00:00
But with this kind of writing, it can only be handled by development, not dynamically removed. For this reason, NocoBase provides a pluggable `app.plugin()` interface for adding and removing middleware. After the modification, the code is as follows.
2021-10-28 14:55:51 +00:00
```ts
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
}
}
});
```
2021-10-31 01:44:52 +00:00
- Distilling the parameters of ratelimit goes a step further by giving the parameter configuration to the plugin management panel
- When the plugin is active, execute plugin.enable() to add ratelimit to it
- When the plugin is disabled, execute plugin.disable() to remove ratelimit
2021-10-28 14:55:51 +00:00
2021-10-31 01:44:52 +00:00
The above is the core content of the plugin, any functional extension can be handled in this way. Just two steps.
2021-10-28 14:55:51 +00:00
2021-10-31 01:44:52 +00:00
- Implement the enable interface of the plugin for adding functionality.
- Then implement the disable interface for removing the function module.
2021-10-28 14:55:51 +00:00
```ts
class MyPlugin extends Plugin {
enable() {
2021-10-31 01:44:52 +00:00
// Logic for adding
2021-10-28 14:55:51 +00:00
}
disable() {
2021-10-31 01:44:52 +00:00
// Logic to remove
2021-10-28 14:55:51 +00:00
}
}
```
2021-10-31 01:44:52 +00:00
**Is it possible not to implement disable? **
2021-10-28 14:55:51 +00:00
2021-10-31 01:44:52 +00:00
The disable interface is designed to enable hot-plugging of plugins so that applications can activate and disable plugins without rebooting. If a plugin does not need to be disabled, you can also just implement the enable interface.