插件

插件机制是我们框架的一大特色。它不但可以保证框架核心的足够精简、稳定、高效,还可以促进业务逻辑的复用,生态圈的形成。有人可能会问了

接下来我们就来逐一讨论

# 为什么要插件

我们在使用 Koa 中间件过程中发现了下面一些问题:

  1. 中间件加载其实是有先后顺序的,但是中间件自身却无法管理这种顺序,只能交给使用者。这样其实非常不友好,一旦顺序不对,结果可能有天壤之别。
  2. 中间件的定位是拦截用户请求,并在它前后做一些事情,例如:鉴权、安全检查、访问日志等等。但实际情况是,有些功能是和请求无关的,例如:定时任务、消息订阅、后台逻辑等等。
  3. 有些功能包含非常复杂的初始化逻辑,需要在应用启动的时候完成。这显然也不适合放到中间件中去实现。

综上所述,我们需要一套更加强大的机制,来管理、编排那些相对独立的业务逻辑。

# 中间件、插件、应用的关系

一个插件其实就是一个『迷你的应用』,和应用(app)几乎一样:

他们的关系是:

# 使用插件

插件一般通过 npm 模块的方式进行复用:

$ npm i egg-mysql --save

注意:我们建议通过 ^ 的方式引入依赖,并且强烈不建议锁定版本。

{
"dependencies": {
"egg-mysql": "^3.0.0"
}
}

然后需要在应用或框架的 config/plugin.js 中声明:

// config/plugin.js
// 使用 mysql 插件
exports.mysql = {
enable: true,
package: 'egg-mysql',
};

就可以直接使用插件提供的功能:

app.mysql.query(sql, values);

# 参数介绍

plugin.js 中的每个配置项支持:

# 开启和关闭

在上层框架内部内置的插件,应用在使用时就不用配置 package 或者 path,只需要指定 enable 与否:

// 对于内置插件,可以用下面的简洁方式开启或关闭
exports.onerror = false;

# 根据环境配置

同时,我们还支持 plugin.{env}.js 这种模式,会根据运行环境加载插件配置。

比如定义了一个开发环境使用的插件 egg-dev,只希望在本地环境加载,可以安装到 devDependencies

// npm i egg-dev --save-dev
// package.json
{
"devDependencies": {
"egg-dev": "*"
}
}

然后在 plugin.local.js 中声明:

// config/plugin.local.js
exports.dev = {
enable: true,
package: 'egg-dev',
};

这样在生产环境可以 npm i --production 不需要下载 egg-dev 的包了。

**注意: **

# package 和 path

// config/plugin.js
const path = require('path');
exports.mysql = {
enable: true,
package: path.join(__dirname, '../lib/plugin/egg-mysql'),
};

# 插件配置

插件一般会包含自己的默认配置,应用开发者可以在 config.default.js 覆盖对应的配置:

// config/config.default.js
exports.mysql = {
client: {
host: 'mysql.com',
port: '3306',
user: 'test_user',
password: 'test_password',
database: 'test',
},
};

具体合并规则可以参见配置

# 插件列表

# 如何开发一个插件

参见文档:插件开发