你可能会发现,sword的代码仓库使用了monorepo,在packages这个目录中,我们定义了很多官方插件,比如在server中的运行时,比如log插件,它们都有自己的作用,而这些插件都是基于sword插件系统上实现的。
在这一章节中,我们将会简单了解sword插件系统是什么样子的,它提供了一些什么功能?
如何写一个插件
在sword中提供了很多root节点,比如log 节点,server节点,在sword运行时中,会注册插件,并且在运行过程中把对应方法执行时机交由插件实现,听起来很简单,做起来也很简单,这是一个插件的类型:
export type Plugin = {
name: string;
// 提供几个钩子用来定义函数,作为框架runtime的shim
server?: {
start: (...args: any[]) => Promise<void> | void;
};
log?: {
err: (v: string | Error) => void;
info: (v: string) => void;
success: (v: string) => void;
};
// 还有其他的root节点,具体内容参见插件系统的子文档
};
可以清楚的看到,有一个plugin name,这个name主要用在日志上,可以打印出某个时机执行的逻辑是由sword实现的,还是某个插件实现的,这会方便调试,所以name并不是一个唯一值。
sword不同于其他框架的插件系统,它可以一个插件同时实现多个root节点,即我写了一个插件叫做:“seho-plugin”,代表了我一个插件实现了多个功能,这样做有一个好处就是,用户在选择插件的时候可以选择又大又全的插件,而不用一个一个添加组合,可以让应用程序的开发始终是“最佳方案”。那么既然一个插件可以实现多个root,那如果你注册了多个插件,运行时同一时间只会运行一个root,那么在sword中采取的措施就是,新的root替换旧的root
比如我写了一个seho-plugin(伪代码演示):
export const plugin = (): Plugin => {
return {
name: 'seho-plugin',
log: () => {
console.log("这是旧的log")
},
server: () => {
console.log("这是旧的server")
}
};
};
我又注册了一个叫做server的插件
export const plugin = (): Plugin => {
return {
name: 'server',
log: () => {},
server: () => {
console.log("这是新的server")
}
};
};
那么此时sword会应用这样的一个插件对象:
{
log: () => {
console.log("这是旧的log")
},
server: () => {
console.log("这是新的server")
}
};
所以sword的插件系统给用户了最大的选择权,你可以让你的插件是颗粒度小的,也可以让你的插件是大而全的,所以我们写插件也非常简单,我们只需要导出一个插件对象就可以啦!
下面演示了一个log插件的开发:
import chalk from 'chalk';
import type { Plugin } from '@swordjs/sword-framework';
const now = () => {
const _ = new Date();
return `${_.getFullYear()}-${_.getMonth() + 1}-${_.getDate()} ${_.getHours()}:${_.getMinutes()}:${_.getSeconds()}`;
};
export const log = {
err: (v: string | Error): void => {
console.log(`${chalk.gray(now())} ${v}`);
},
info: (v: string): void => {
console.log(`${chalk.gray(now())} ${chalk.yellow(v)}`);
},
success: (v: string): void => {
console.log(`${chalk.gray(now())} ${chalk.green(v)}`);
}
};
/**
* 定义终端打印日志插件
* @preset true
* @return {*}
*/
export const useLogPlugin = (): Plugin => {
return {
name: 'log',
log
};
};
使用插件
import { useApp, usePlugin } from '@swordjs/sword-framework';
const plugin = usePlugin();
plugin.add(useLogPlugin);
const app = useApp();
const init = () => {
// ...
};
init();
这里useplugin的类型:
declare const usePlugin: () => {
add: (plugin: Plugin | (() => Plugin)) => Promise<Plugin[]>;
};