Egg 插件

2020-02-06 14:10 更新

插件機制是我們框架的一大特色。它不但可以保證框架核心的足夠精簡、穩(wěn)定、高效,還可以促進(jìn)業(yè)務(wù)邏輯的復(fù)用,生態(tài)圈的形成。有人可能會問了

  • Koa 已經(jīng)有了中間件的機制,為啥還要插件呢?
  • 中間件、插件、應(yīng)用它們之間是什么關(guān)系,有什么區(qū)別?
  • 我該怎么使用一個插件?
  • 如何編寫一個插件?
  • ...

接下來我們就來逐一討論

為什么要插件

我們在使用 Koa 中間件過程中發(fā)現(xiàn)了下面一些問題:

  1. 中間件加載其實是有先后順序的,但是中間件自身卻無法管理這種順序,只能交給使用者。這樣其實非常不友好,一旦順序不對,結(jié)果可能有天壤之別。
  2. 中間件的定位是攔截用戶請求,并在它前后做一些事情,例如:鑒權(quán)、安全檢查、訪問日志等等。但實際情況是,有些功能是和請求無關(guān)的,例如:定時任務(wù)、消息訂閱、后臺邏輯等等。
  3. 有些功能包含非常復(fù)雜的初始化邏輯,需要在應(yīng)用啟動的時候完成。這顯然也不適合放到中間件中去實現(xiàn)。

綜上所述,我們需要一套更加強大的機制,來管理、編排那些相對獨立的業(yè)務(wù)邏輯。

中間件、插件、應(yīng)用的關(guān)系

一個插件其實就是一個『迷你的應(yīng)用』,和應(yīng)用(app)幾乎一樣:

他們的關(guān)系是:

  • 應(yīng)用可以直接引入 Koa 的中間件。
  • 當(dāng)遇到上一節(jié)提到的場景時,則應(yīng)用需引入插件。
  • 插件本身可以包含中間件。
  • 多個插件可以包裝為一個上層框架。

使用插件

插件一般通過 npm 模塊的方式進(jìn)行復(fù)用:

$ npm i egg-mysql --save

注意:我們建議通過 ^ 的方式引入依賴,并且強烈不建議鎖定版本。

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

然后需要在應(yīng)用或框架的 config/plugin.js 中聲明:

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

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

app.mysql.query(sql, values);

參數(shù)介紹

plugin.js 中的每個配置項支持:

  • {Boolean} enable - 是否開啟此插件,默認(rèn)為 true
  • {String} package - npm 模塊名稱,通過 npm 模塊形式引入插件
  • {String} path - 插件絕對路徑,跟 package 配置互斥
  • {Array} env - 只有在指定運行環(huán)境才能開啟,會覆蓋插件自身 package.json 中的配置

開啟和關(guān)閉

在上層框架內(nèi)部內(nèi)置的插件,應(yīng)用在使用時就不用配置 package 或者 path,只需要指定 enable 與否:

// 對于內(nèi)置插件,可以用下面的簡潔方式開啟或關(guān)閉
exports.onerror = false;

根據(jù)環(huán)境配置

同時,我們還支持 plugin.{env}.js 這種模式,會根據(jù)運行環(huán)境加載插件配置。

比如定義了一個開發(fā)環(huán)境使用的插件 egg-dev,只希望在本地環(huán)境加載,可以安裝到 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',
};

這樣在生產(chǎn)環(huán)境可以 npm i --production 不需要下載 egg-dev 的包了。

注意:

  • 不存在 plugin.default.js
  • 只能在應(yīng)用層使用,在框架層請勿使用。

package 和 path

  • package 是 npm 方式引入,也是最常見的引入方式
  • path 是絕對路徑引入,如應(yīng)用內(nèi)部抽了一個插件,但還沒達(dá)到開源發(fā)布獨立 npm 的階段,或者是應(yīng)用自己覆蓋了框架的一些插件
  • 關(guān)于這兩種方式的使用場景,可以參見漸進(jìn)式開發(fā)。
// config/plugin.js
const path = require('path');
exports.mysql = {
enable: true,
path: path.join(__dirname, '../lib/plugin/egg-mysql'),
};

插件配置

插件一般會包含自己的默認(rèn)配置,應(yīng)用開發(fā)者可以在 config.default.js 覆蓋對應(yīng)的配置:

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

具體合并規(guī)則可以參見配置。

插件列表

如何開發(fā)一個插件

參見文檔:插件開發(fā)。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號