我想要实现的目标:
我想为给定产品开发一个核心浏览器库。有些部分的函数实现会根据自定义而有所不同(我们将其称为插件函数)。我想避免在库代码中管理这些插件函数,我想在不同的代码库中管理它们,并且只在 CI/CD 期间安装它们,这样我就可以将它们包含在捆绑包中。
应用程序配置告诉系统选择哪个插件功能,我们假设客户 1 选择
foo
,客户 2 选择 bar
。如果核心库获得一个参数来识别要调用的正确函数,那就太好了。
到目前为止我所做的:
在运行时,我不知道如何在没有“显式”if 语句的情况下调用实现。我认为唯一可行的方法是使用decorators。该配置将包含一个唯一的名称,因此我可以搜索给定的函数。
我从这个每个插件都应该使用的装饰器开始
function pluginFunc(name: string) {
console.log(`plugin func '${name}'`);
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
console.log({ name, target, propertyKey, descriptor });
};
}
export { pluginFunc };
还有一个自定义插件
import { pluginFunc } from "./pluginFunc";
@pluginFunc("foo")
function pluginOne() {
console.log("hello from plugin 1");
}
export { pluginOne }
现在我想在一个简单的 index.ts 文件中测试我的方法
/* async */ function callPlugin(name: string) {
// find function by decorator and name and call it
}
callPlugin('foo');
是否可以通过装饰器
pluginFunc
和给定名称找到一个函数(无需在构建期间导入它!)?
如果这是不可能的,那么更简单的方法是通过函数的名称来调用函数(而不导入它)呢?
保持愚蠢的简单:
// index.ts
import hooks from './hooks.ts';
hooks.foo();
// hooks.ts
export default {
foo() {}, // noop, or default implementation
};
// plugin.ts
import hooks from './hooks.ts';
hooks.foo = function pluginOne() {
console.log("hello from plugin 1");
};
这是基本模式。如果您不喜欢简单的分配,当然可以使钩子注册更复杂,并使用类似
registerHook('foo', function pluginOne() { … });
或那些花哨的装饰器。假设 plugin.ts 在启动时以某种方式加载 - 无论您是在某个地方使用 import './plugin.ts';
、特殊的插件加载器函数,还是通过环境或构建过程来加载,都取决于您。