首页 文章

如何从运行时已知的文件中加载Typescript模块(在angular2电子中)

提问于
浏览
1

我正在尝试编写一个小概念证明,以确定 "Angular2 in typescript + Electron" 是否满足未来桌面应用程序项目的要求 .

但是我遇到了麻烦... Am I trying to achieve the impossible or is there a way to do it? Here's my context:


Short version:

我怎样才能运行:

@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"

Long Version with Context:

核心要求是一种“动态前端插件系统”,正如我所说的那样 . 这意味着:我的UI的一部分必须在运行时可替换 - 但我不知道将提前插入的组件 .

Example scenario:

我的应用程序收到“foo”事件:

leEvent: { eventtype: 'foo', payload: '...' }

所以它会告诉它的插件管理器:嘿我需要一个UI组件来呈现'foo'事件 .

The plugin manager searches for a 'fooplugin.ts' file 包含组件 loads the component class from this file dynamically 并返回类型 . 如果它现在没有foo插件,用户可以将该文件从插件市场下载到插件文件夹,然后再次尝试 .

我的应用程序然后使用DynamicComponentLoader.loadIntoLocation将此动态加载的类型集成到dom,然后告诉组件呈现(leEvent) .

最后一部分动态加载组件的角度是没问题的,我的 pain point is the plugin manager method to load a class from a file ...到目前为止我得到的最好的是:

@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;
  }
}

我用“--module commonjs”运行我的tsc .

当我调用该方法时,它告诉我“../mtplugins/foorendererplugin.ts未被声明为依赖项”......好吧,我不能提前声明依赖项,因为它只在运行时已知 .


那么,有没有办法从只在运行时知道的文件中加载typescript类? In Java I think I would do it with a Classloader, so i feel like I need typescript's counterpart of that thing . 我其实以为我've read that typescript with commonjs and require() would support this, so maybe this mechanism and angular'的system.js集成是否相互咬合?

我是angular2和打字稿以及电子和节点的新手,所以如果我忽略了一些基本的东西,请原谅 .


EDIT

正如Louy所指出的那样,错误消息不是特定于打字稿的 . 它是由System.js引发的......

事实证明,花在学习您想要使用的技术上的更多时间总是一项很好的投资 . 事实上,我在这里做了一个新手错误:混合不同的模块加载系统 . 我认为我必须使用CommonJS才能在运行时加载外部模块,但System.js也很好地支持运行时加载 - 这意味着:

代替

require(..)

我只是不得不使用

declare var System: any; //System.js Loader
...
System.import('./app/' + eventtype+ 'plugin.js');

然后你所要做的就是保持插件独立于应用程序核心的实际代码(因为这会导致模块混乱......并且无论是哪种架构气味),而只依赖于接口(Typescript ftw!) .

这就是你的可插拔angular2 UI所需要的:)

1 回答

  • 0

    为什么不写一个对象字典?你不会以这种方式失去类型 .

    // 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];
    

相关问题