如何将动态外部组件加载到 Angular 应用程序中
Posted
技术标签:
【中文标题】如何将动态外部组件加载到 Angular 应用程序中【英文标题】:How to load dynamic external components into Angular application 【发布时间】:2018-01-12 04:44:03 【问题描述】:我遇到了 Angular 应用程序的问题。
我想要一个用 Typscript 编写的 Angular 应用程序,使用 (aot) 构建。
目的是显示带有一些小部件的用户仪表板。小部件是一个角度组件。
我的应用带有一些嵌入式小部件。 但是小部件应该通过市场之类的东西进行扩展;或手动创建。
市场应该将文件(js/ts/bunlde..??)下载到特定文件夹中。
然后我的应用应该能够加载新的小部件(= ng 组件)并实例化它们。
我的文件夹结构(生产)
|- 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。 所以目标是动态加载文件并实例化包含的组件。
我尝试了很多解决方案,使用“require”和“System.import”,但在动态生成加载路径时都失败了。
这应该是可能的吗? 我可以改变我的代码结构;更改外部小部件..(例如,widgetB 尚未转译,...)
事实上,我正在寻找一个带有 Angular4/webpack 应用程序的“插件系统”。
【问题讨论】:
【参考方案1】:我正在做同样的事情。我在 NgConf 的this talk 中解释了详细信息。
首先要了解的是,Webpack 不能在构建时动态加载未知的模块。这是 Webpack 构建依赖树并在构建时收集模块标识符的方式所固有的。这很好,因为 Webpack 是一个模块捆绑器,而不是模块加载器。所以你需要使用模块加载器,而现在唯一可行的选择是 SystemJS。
然后,每个插件都应该打包成一个模块,并且所有导出的组件都应该添加到该模块的entryComponents
。
在运行时,您将加载该模块以访问其内部声明的组件。你并不真的需要一个模块,但它是 Angular 中的一个打包单元,所以你不能避免使用它。现在,一旦你得到一个模块,你必须根据模块是否使用 AOT 构建来选择。
如果它是使用 AOT 构建的,你只需从模块中获取导出的工厂类并创建一个模块实例:
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 编译器进行编译:
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);
然后,您可以使用本文中描述的技术在任意位置添加动态组件:Here is what you need to know about dynamic components in Angular
【讨论】:
您的方法很有趣,是否可以使用这种方式导入远程托管的组件/模块? @Seb,是的,但是你需要使用 SystemJS 来做这个 太好了,可以为我解决问题!你有任何关于如何集成 systemJs 和 webpack 的例子吗?还有一个远程组件的 System.import 示例? 你使用 angular-cli 吗? 我在 github 上创建了一个存储库,其解决方案可能会有所帮助。它使用 Angular 6 个库和 1 个基础应用程序,懒惰地加载 UMD 捆绑库; github.com/lmeijdam/angular-umd-dynamic-example如果有什么建议,欢迎补充! PS:它远非完美,但它至少在运行时加载“未知”库。需要寻找“评估”替代方案以上是关于如何将动态外部组件加载到 Angular 应用程序中的主要内容,如果未能解决你的问题,请参考以下文章
如何将第 3 方脚本从 Web 动态加载到 Angular2 组件中
如何在作为 innerHtml 加载的文档的子部分中动态加载 Angular 组件?