如何从运行时已知的文件加载 Typescript 模块(在 angular2+electron 中)
How to load Typescript module from a file known at runtime (in angular2+electron)
我正在尝试写一些概念证明,以确定 "Angular2 in typescript + Electron" 是否会满足未来桌面应用程序项目的要求。
但我遇到了麻烦... 我是在努力实现不可能的目标还是有办法做到这一点?这是我的上下文:
短版:
我该怎么做运行:
@Injectable()
export class PluginManager {
getPluginComponentForEventType(eventtype: string): Type {
//return is angular "Type", later consumed by Dynamic Loader
var externalModule = require('../mtplugins/' + eventtype + 'plugin.ts');
return externalModule.TheRenderer;
}
}
没有出现此错误:
"../mtplugins/foorendererplugin.ts not declared as a dependency"
带上下文的长版本:
核心要求是一种 "dynamic frontend plugin system",我会这样称呼它。这意味着:我的 UI 的一部分必须在 运行 时可替换 - 但我不知道将提前插入那里的组件。
示例场景:
我的应用收到一个 "foo" 事件:
leEvent: { eventtype: 'foo', payload: '...' }
所以它会告诉它的插件管理器:嘿,我需要一个 UI 组件来渲染一个 'foo' 事件。
插件管理器搜索包含组件的'fooplugin.ts'文件,从该文件动态加载组件class 和 returns 类型。如果现在没有foo插件,用户可以从插件市场下载这个文件到插件文件夹,然后再试。
我的应用程序然后使用 DynamicComponentLoader.loadIntoLocation 将这个动态加载的类型集成到 dom,然后告诉组件呈现(leEvent)。
这最后一部分在angular中动态加载组件没问题,我的痛点是插件管理器方法从文件加载class...到目前为止我得到的最好的东西是:
@Injectable()
export class PluginManager {
getPluginComponentForEventType(eventtype: string): Type {
//return is angular "Type", later consumed by Dynamic Loader
var externalModule = require('../mtplugins/' + eventtype + 'plugin.ts');
return externalModule.TheRenderer;
}
}
我 运行 我的 tsc 带有“--module commonjs”。
当我调用该方法时,它告诉我“../mtplugins/foorendererplugin.ts 未声明为依赖项”...好吧,我无法提前声明依赖项,因为它仅在 运行时间。
那么,有没有办法从仅在 运行 时间已知的文件中加载打字稿 classes? 在 Java 中,我想我会用类加载器来完成它,所以我觉得我需要打字稿的对应物 。我实际上认为我已经读过带有 commonjs 和 require() 的打字稿会支持这一点,所以也许这种机制和 angular 的 system.js 集成正在互相攻击?
我是 angular2、typescript、electron 和 node 的新手,所以如果我忽略了一些基本的东西,请原谅。
编辑
正如 Louy 所指出的,错误消息与打字稿无关。它是由 System.js...
抛出的
再次证明,花更多时间学习您想要使用的技术始终是一项不错的投资。事实上,我在这里犯了一个新手错误:混淆了不同的模块加载系统。我以为我必须使用 CommonJS 才能在 运行 时间加载外部模块,但是 运行 时间加载也得到了 System.js 的很好支持 - 这意味着:
而不是
require(..)
我只需要使用
declare var System: any; //System.js Loader
...
System.import('./app/' + eventtype+ 'plugin.js');
那么你所要做的就是让插件独立于应用程序核心的实际代码(因为这会导致模块混乱......并且无论哪种方式都是一种架构气味),而不是仅依赖于接口(Typescript ftw! ).
这就是您的可插拔 angular2 UI :)
所需的全部内容
为什么不制作一个对象字典呢?这样你就不会丢失类型。
// import all of them...
import pluginA from '../mtplugins/Aplugin.ts'
// add all here
const plugins: {[name: string]: /*typeof plugin*/} = {
a: pluginA,
// ...
}
// and then...
var externalModule = plugins[eventtype];
我正在尝试写一些概念证明,以确定 "Angular2 in typescript + Electron" 是否会满足未来桌面应用程序项目的要求。
但我遇到了麻烦... 我是在努力实现不可能的目标还是有办法做到这一点?这是我的上下文:
短版:
我该怎么做运行:
@Injectable()
export class PluginManager {
getPluginComponentForEventType(eventtype: string): Type {
//return is angular "Type", later consumed by Dynamic Loader
var externalModule = require('../mtplugins/' + eventtype + 'plugin.ts');
return externalModule.TheRenderer;
}
}
没有出现此错误:
"../mtplugins/foorendererplugin.ts not declared as a dependency"
带上下文的长版本:
核心要求是一种 "dynamic frontend plugin system",我会这样称呼它。这意味着:我的 UI 的一部分必须在 运行 时可替换 - 但我不知道将提前插入那里的组件。
示例场景:
我的应用收到一个 "foo" 事件:
leEvent: { eventtype: 'foo', payload: '...' }
所以它会告诉它的插件管理器:嘿,我需要一个 UI 组件来渲染一个 'foo' 事件。
插件管理器搜索包含组件的'fooplugin.ts'文件,从该文件动态加载组件class 和 returns 类型。如果现在没有foo插件,用户可以从插件市场下载这个文件到插件文件夹,然后再试。
我的应用程序然后使用 DynamicComponentLoader.loadIntoLocation 将这个动态加载的类型集成到 dom,然后告诉组件呈现(leEvent)。
这最后一部分在angular中动态加载组件没问题,我的痛点是插件管理器方法从文件加载class...到目前为止我得到的最好的东西是:
@Injectable()
export class PluginManager {
getPluginComponentForEventType(eventtype: string): Type {
//return is angular "Type", later consumed by Dynamic Loader
var externalModule = require('../mtplugins/' + eventtype + 'plugin.ts');
return externalModule.TheRenderer;
}
}
我 运行 我的 tsc 带有“--module commonjs”。
当我调用该方法时,它告诉我“../mtplugins/foorendererplugin.ts 未声明为依赖项”...好吧,我无法提前声明依赖项,因为它仅在 运行时间。
那么,有没有办法从仅在 运行 时间已知的文件中加载打字稿 classes? 在 Java 中,我想我会用类加载器来完成它,所以我觉得我需要打字稿的对应物 。我实际上认为我已经读过带有 commonjs 和 require() 的打字稿会支持这一点,所以也许这种机制和 angular 的 system.js 集成正在互相攻击?
我是 angular2、typescript、electron 和 node 的新手,所以如果我忽略了一些基本的东西,请原谅。
编辑
正如 Louy 所指出的,错误消息与打字稿无关。它是由 System.js...
抛出的再次证明,花更多时间学习您想要使用的技术始终是一项不错的投资。事实上,我在这里犯了一个新手错误:混淆了不同的模块加载系统。我以为我必须使用 CommonJS 才能在 运行 时间加载外部模块,但是 运行 时间加载也得到了 System.js 的很好支持 - 这意味着:
而不是
require(..)
我只需要使用
declare var System: any; //System.js Loader
...
System.import('./app/' + eventtype+ 'plugin.js');
那么你所要做的就是让插件独立于应用程序核心的实际代码(因为这会导致模块混乱......并且无论哪种方式都是一种架构气味),而不是仅依赖于接口(Typescript ftw! ).
这就是您的可插拔 angular2 UI :)
所需的全部内容为什么不制作一个对象字典呢?这样你就不会丢失类型。
// import all of them...
import pluginA from '../mtplugins/Aplugin.ts'
// add all here
const plugins: {[name: string]: /*typeof plugin*/} = {
a: pluginA,
// ...
}
// and then...
var externalModule = plugins[eventtype];