如何将动态外部组件加载到 Angular 应用程序中
How to load dynamic external components into Angular application
我遇到了 Angular 应用程序的问题。
我想要一个 angular 应用程序,用 Typscript 构建,使用 (aot)。
目的是显示带有一些小部件的用户仪表板。小部件是 angular 组件。
我的应用程序带有一些嵌入式小部件。
但是小部件应该通过像市场这样的东西来扩展;或手动创建。
市场应将文件 (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 应用程序的 "plugin system"。
我也在做同样的事情。我在 NgConf this talk 中解释了详细信息。
首先要了解的是,Webpack 无法在构建时动态加载未知的模块。这是 Webpack 在构建期间构建依赖树和收集模块标识符的方式所固有的。而且它非常好,因为 Webpack 是一个模块打包器,而不是模块加载器。所以你需要使用模块加载器,现在唯一可行的选择是 SystemJS。
然后,每个插件都应该打包成一个模块,所有导出的组件都应该添加到那个模块的entryComponents
。
在运行时,您将加载该模块以访问其中声明的组件。你并不真的需要一个模块,但它是 Angular 中的一个包装单元,所以你无法避免使用它。现在,一旦你得到一个模块,你必须根据模块是否使用 AOT 构建来进行选择。
如果它是使用 AOT 构建的,您只需从模块中获取导出的工厂 class 并创建一个模块实例:
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
我遇到了 Angular 应用程序的问题。
我想要一个 angular 应用程序,用 Typscript 构建,使用 (aot)。
目的是显示带有一些小部件的用户仪表板。小部件是 angular 组件。
我的应用程序带有一些嵌入式小部件。 但是小部件应该通过像市场这样的东西来扩展;或手动创建。
市场应将文件 (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 应用程序的 "plugin system"。
我也在做同样的事情。我在 NgConf this talk 中解释了详细信息。
首先要了解的是,Webpack 无法在构建时动态加载未知的模块。这是 Webpack 在构建期间构建依赖树和收集模块标识符的方式所固有的。而且它非常好,因为 Webpack 是一个模块打包器,而不是模块加载器。所以你需要使用模块加载器,现在唯一可行的选择是 SystemJS。
然后,每个插件都应该打包成一个模块,所有导出的组件都应该添加到那个模块的entryComponents
。
在运行时,您将加载该模块以访问其中声明的组件。你并不真的需要一个模块,但它是 Angular 中的一个包装单元,所以你无法避免使用它。现在,一旦你得到一个模块,你必须根据模块是否使用 AOT 构建来进行选择。
如果它是使用 AOT 构建的,您只需从模块中获取导出的工厂 class 并创建一个模块实例:
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