如何使用打字稿构建插件系统

拍摄者詹姆斯·哈里森onUnplash

如果您要构建简约应用程序,则可以使用插件来扩展您的应用程序的一种方法之一。插件通常是使用裸露的API或库修改并添加功能到应用程序的代码的小包装。通常在运行时加载,它们使应用程序更加灵活。

在本教程中,我们将创建一个可以在任何应用中使用的简单类型安全插件系统。

入门

Let’s start by creating a fresh Node.js project. I’ll be usingnpm作为本教程中的包裹经理,但请随时跟随

1。mkdir my-plugin-manager

2。cd my-plugin-manager

3。npm init -y

4。NPM I -D打字稿

Defining a plugin

我们将使用一个抽象类每个插件都实现。我们将需要提供名称和版本,以及分别加载插件的启动和停止方法。

我们可以使用一个接口实现此功能,然后为每个插件实现,但是我们还希望提供一种访问其他API的方法。否则,该插件在其自己的范围之外不会做太多。因此,我们将使插件为抽象类,并需要通用类型的输入`app'。这可能是您的应用程序的主要类,一个包含对多个有用API的对象,也可能是您的插件可能想要访问的任何其他方法或值。

导出抽象类Plugintemplate  {
abstract name: string;
抽象版本:字符串;
应用:T;构造函数(app:t){
this.app = app;
}
抽象开始():Promise ;
abstract stop(): Promise;
}

实现类时,插件必须提供名称,版本,启动和停止方法。插件的示例,例如应用程序上课是…

导出默认类myplugin扩展了Plugintemplate  {
名称=“ my-plugin”;
版本=“ 1.0.0”;
异步开始(){
console.log("My plugin started");
}
异步stop(){
console.log(“我的插件停止”);
}
}

管理多个插件

为了帮助加载和卸载插件,我们可以创建一个插件管理器类。通常,该类将通过应用程序的主要类实例化一次。

首先,让我们创建一个具有通用类型的新课程t。像通用Plugintemplateclass, this represents the object to be exposed to the plugins. Active plugins will be stored in aprivate _plugins类要使用的字段自己的方法(例如卸载方法)。

导出类PluginManager  {
私人_plugins:Plugintemplate [] = [];
异步负载(插件:Plugintemplate ){
this._plugins.push(plugin);
等待plugin.start();
}
异步卸载(pluginname:string){
让插件= this._plugins.find(plugin => plugin.name === pluginname);
如果(!插件)返回false;
等待plugin.stop();
返回true;
}
}

为了使来自文件系统的加载插件更容易,我们可以创建一种方法,该方法从目录中读取所有文件,并将该目录中的任何文件加载为插件。

异步LOADDIR(APP:T,DIR:String){
让文件=等待fs.ReadDir(dir);
(让文件文件){
//当前工作用于解析插件目录的路径。
让插件=等待导入(path.join(process.cwd(),dir,file));
让插件=新插件(app);
等待this.load(插件为plugintemplate );
}
}

And to aid with unloading plugins, for example when an app is stopped, we’ll create a method to unload each function from the_plugins场地。

异步UnloadAll(){
for(让this._plugins的插件){
等待plugin.stop();
}
}

添加一个应用程序

我们可以通过我们希望的任何通用t,但最有可能的类型将是应用程序的主要类别。该类还可能保留插件管理器实例。要用一块石头杀死两只鸟,让我们嘲笑一个应用程序class, with apluginManager。We can load plugins from the。/plugins目录在当前工作目录(您启动应用程序的目录)中找到。

导出类应用程序{
pluginManager = new PluginManager ();
constructor(){}开始() {
this.pluginmanager.loaddir(this,'./plugins')
}
停止() {
this.pluginmanager.unloadall();
}
}

方便的打字稿快捷方式

我们可以定义简化用法的快捷方式,而不是每次执行诸如创建插件之类的事情时将其用作通用的类型。

导出类型appplugin = Punicintemplate ;// 老的
导出默认类myplugin扩展了Plugintemplate {。。。}
// 新的
export default class MyPlugin extends AppPlugin {...}

结论

将类型安全添加到插件系统中,可以使开发体验更快,更安全。但是,不要忘记揭露正确的类型,例如您的应用程序/插件API和任何快捷方式类型。如果您要面对挑战,请尝试将其与您现有的应用程序集成在一起。

更多内容plainenglish.io。注册我们免费每周新闻通讯。跟随us ontwitter,,,,LinkedIn,,,,YouTube, 和Discord对成长黑客感兴趣?查看电路

每天新的JavaScript和Web开发内容。关注加入3M+每月读者。

Get the Medium app

一个说“在应用商店上下载”的按钮,如果单击,它将带您到iOS App Store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Baidu