Plugin
12003The plugin mechanism is a major feature of our framework. It not only ensures that the core of the framework remains sufficiently streamlined, stable, and efficient, but also promotes the reuse of business logic and the formation of an ecosystem. Some may ask:
- Koa already has a middleware mechanism; why do we need plugins?
- What is the relationship between middleware, plugins, and applications? What are the differences among them?
- How do I use a plugin?
- How do I write a plugin?
Next, we will discuss these questions one by one.
Why Use Plugins
During our use of Koa middleware, we encountered the following issues:
- Middleware loading actually has a sequence, but the middleware itself cannot manage this order and must leave it to the user. This is quite unfriendly; if the order is incorrect, the results can vary greatly.
- The role of middleware is to intercept user requests and perform some actions before and after, such as authentication, security checks, access logs, etc. However, in reality, some functionalities are unrelated to requests, such as scheduled tasks, message subscriptions, background logic, etc.
- Some functionalities involve very complex initialization logic that needs to be completed when the application starts. Clearly, this is also not suitable for implementation within middleware.
In summary, we need a more powerful mechanism to manage and orchestrate those relatively independent business logics.
Relationship Between Middleware, Plugins, and Applications
A plugin is essentially a "mini-application," almost identical to an application (app):
- It includes Service, Middleware, Configuration, Framework Extensions, etc.
- It does not have an independent Router and Controller.
- It does not have
plugin.js, and can only declare dependencies on other plugins, but cannot decide whether other plugins are enabled or not.
Their relationships are:
- Applications can directly import Koa's middleware.
- When encountering the scenarios mentioned in the previous section, applications need to import plugins.
- Plugins themselves can contain middleware.
- Multiple plugins can be packaged into a higher-level framework.
Using Plugins
Plugins are typically reused through npm modules:
$ npm i egg-mysql --saveNote: We recommend introducing dependencies using the ^ notation and strongly advise against locking versions.
{
"dependencies": {
"egg-mysql": "^3.0.0"
}
}Next, you need to declare it in the application's or framework's config/plugin.js:
// config/plugin.js
// Use mysql plugin
exports.mysql = {
enable: true,
package: 'egg-mysql',
};This allows you to directly use the functionality provided by the plugin:
app.mysql.query(sql, values);Parameter Introduction
Each configuration item in plugin.js supports:
{Boolean} enable- Whether to enable this plugin, default is true{String} package-npmmodule name, used to import the plugin vianpmmodule{String} path- Absolute path of the plugin, mutually exclusive with package configuration{Array} env- Only enabled in specified running environments, will override the plugin's own configuration inpackage.json
Enabling and Disabling
For built-in plugins in the higher-level framework, applications can use them without configuring package or path, just specify enable:
// For built-in plugins, you can use the following concise way to enable or disable
exports.onerror = false;Configuring by Environment
Additionally, we support the plugin.{env}.js pattern, which will load plugin configurations based on the running environment.
For example, if you define a plugin egg-dev that is only used in the development environment and want to load it only in the local environment, you can install it in devDependencies.
// npm i egg-dev --save-dev
// package.json
{
"devDependencies": {
"egg-dev": "*"
}
}Next, declare it in plugin.local.js:
// config/plugin.local.js
exports.dev = {
enable: true,
package: 'egg-dev',
};This way, when executing npm i --production in the production environment, the egg-dev package does not need to be downloaded.
Note:
plugin.default.jsdoes not exist- Can only be used at the application level, do not use at the framework level.
Package and Path
packageis the npm way of importing, and it is the most common way.pathis for absolute path imports, for example, if an application has extracted a plugin internally but has not yet published it to npm; or if the application has rewritten certain plugins of the framework.- For usage scenarios of these two methods, refer to the Progressive Development document.
// config/plugin.js
const path = require('path');
exports.mysql = {
enable: true,
path: path.join(__dirname, '../lib/plugin/egg-mysql'),
};Plugin Configuration
Plugins generally contain their own default configurations. Application developers can override the corresponding configurations in config.default.js:
// config/config.default.js
exports.mysql = {
client: {
host: 'mysql.com',
port: '3306',
user: 'test_user',
password: 'test_password',
database: 'test'
}
};For specific merging rules, refer to Configuration.
Plugin List
- The framework comes with commonly used plugins for enterprise applications by default:
- onerror Unified exception handling
- Session Session implementation
- i18n Multilingual support
- watcher File and folder monitoring
- multipart File streaming upload
- security Security
- development Development environment configuration
- logrotator Log rotation
- schedule Scheduled tasks
- static Static server
- jsonp JSONP support
- view Template engine
- More community plugins can be searched on GitHub egg-plugin.
How to Develop a Plugin
Refer to the documentation: Plugin Development.