如何将动态外部组件加载到Angular应用程序中 [英] How to load dynamic external components into Angular application

查看:102
本文介绍了如何将动态外部组件加载到Angular应用程序中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了Angular应用程序的问题.

I'm facing a problem with Angular application.

我想用(aot)用Typscript编写一个有角度的应用程序.

I would like to have an angular application written in Typscript build with (aot).

目的是显示带有一些小部件的用户仪表板.小部件是一个角度组件.

The aim is to display a user dashboard with some widgets. A widget is an angular component.

我的应用程序带有一些嵌入式小部件. 但是小部件应该通过诸如市场之类的东西来扩展.或手动创建.

My app comes with some embedded widgets. But widgets should be extended by something like a market place; or created manually.

市场应将文件(js/ts/bunlde .. ??)下载到特定文件夹中.

The market should download files (js/ts/bunlde..??) into a specific folder.

然后我的应用程序应该能够加载新的小部件(= ng组件)并实例化它们.

Then my app should be able to load the new widgets (= ng component) and instanciate them.

我的文件夹结构(生产)

My folder structure (production)

  |- index.html
  |- main.f5b448e73f5a1f3f796e.bundle.js
  |- main.f5b448e73f5a1f3f796e.bundle.js.map
  |- .... (all other files generated)
  |- externalWidgets
      |- widgetA
            |- widjetA.js
            |- widjetA.js.map
            |- assets
                 |- image.png
      |- widgetB
            |- widjetB.ts
            |- widjetB.html
            |- widjetB.css

然后,在加载用户页面时,数据库会说有一个widgetA. 因此,目标是动态加载文件并实例化包含的组件.

Then when loading the user page, the database say that there is a widgetA. So the aim is to dynamically load files and instanciate included component.

我尝试过使用"require"和"System.import"的许多解决方案,但是当动态生成加载路径时,两者均失败.

I've tried many solutions, using "require" and "System.import" but both fails when the path to load is dynamically generated.

这应该可行吗? 我可以更改代码结构;更改外部窗口小部件..(例如,尚未转换widgetB,...)

Is this should be possible ? I can change my code structure; change external widgets.. (for example widgetB is not yet transpiled,...)

事实上,我正在寻找带有Angular4/webpack应用程序的插件系统".

In fact I'm looking for a "plugin system" with an Angular4/webpack application.

推荐答案

我做的完全一样.我在NgConf上的此话题中解释了详细信息.

I'm doing exactly the same. And I explain the details in this talk at NgConf.

首先要了解的是,Webpack无法动态加载在构建期间未知的模块.这是Webpack构建依赖关系树并在构建期间收集模块标识符的方式所固有的.由于Webpack是模块捆绑器,而不是模块加载器,因此非常好.因此,您需要使用模块加载器,而现在唯一可行的选择是SystemJS.

The first thing to understand is that Webpack cannot dynamically load modules that are unknown during build time. This is inherent to the way Webpack builds dependency tree and collects modules identifiers during build time. And it's perfectly fine since Webpack is a modules bundler, not modules loader. So you need to use a module loader and the only viable option now is SystemJS.

然后,每个插件都应打包为一个模块,并将所有导出的组件添加到该模块的entryComponents.

Then, each plugin should be packaged as a module and all exported components should be added to the entryComponents of that module.

在运行时,您将加载该模块以访问其中声明的组件.您实际上并不需要模块,但这是Angular中的包装单位,因此您不可避免地要使用它.现在,一旦获得模块,就必须根据模块是否使用AOT进行选择.

During runtime, you will load that module to get access to the components declared inside if it. You don't really need a module but that's a unit of packaging in Angular so you can't avoid using it. Now, once you get a module, you have to options depending on whether the module is built using AOT or not.

如果它是使用AOT构建的,则只需从模块中获取导出的工厂类并创建一个模块实例:

If it's built using AOT, you just get the exported factory class from the module and create a module instance:

System.import('path/to/module').then((module)=>{
    const moduleFactory = module.moduleFactoryClassName;
    const moduleRef = moduleFactory.create(this.parentInjector);
    const resolver = moduleRef.componentFactoryResolver;
    const compFactory = resolver.resolveComponentFactory(AComponent);
}

如果不是使用AOT构建的,则必须使用JIT编译器进行编译:

If it's not built using AOT, you have to compile it using JIT compiler:

System.import('path/to/module').then((module)=>{
    const moduleFactory = this.compiler.compileModuleSync(module.moduleClassName);
    const moduleRef = moduleFactory.create(this.parentInjector);
    const resolver = moduleRef.componentFactoryResolver;
    const compFactory = resolver.resolveComponentFactory(AComponent);
}

然后,您可以使用本文中介绍的技术在任意位置添加动态组件:

Then you can add dynamic components wherever you want using techniques described in this article: Here is what you need to know about dynamic components in Angular

这篇关于如何将动态外部组件加载到Angular应用程序中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆