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

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

问题描述

我在使用 Angular 应用程序时遇到问题.

I'm facing a problem with Angular application.

我想要一个用 Typscript 编写的带有 (aot) 的 Angular 应用程序.

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

然后您可以使用本文中描述的技术在任何地方添加动态组件:这里是你需要了解的关于 Angular 中的动态组件

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天全站免登陆