typescript 如何将动态外部组件加载到 Angular 应用程序中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45503497/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to load dynamic external components into Angular application
提问by jano42
I'm facing a problem with Angular application.
我正面临 Angular 应用程序的问题。
I would like to have an angular application written in Typscript build with (aot).
我想用(aot)用 Typscript 构建一个有角度的应用程序。
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.
我的应用程序带有一些嵌入式小部件。但是小部件应该通过诸如市场之类的东西来扩展;或手动创建。
The market should download files (js/ts/bunlde..??) into a specific folder.
市场应该将文件(js/ts/bunlde..??)下载到特定的文件夹中。
Then my app should be able to load the new widgets (= ng component) and instanciate them.
然后我的应用程序应该能够加载新的小部件(= ng 组件)并实例化它们。
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
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.
然后在加载用户页面时,数据库说有一个widgetA。所以目的是动态加载文件并实例化包含的组件。
I've tried many solutions, using "require" and "System.import" but both fails when the path to load is dynamically generated.
我已经尝试了很多解决方案,使用“require”和“System.import”,但是当加载路径是动态生成的时,两者都失败了。
Is this should be possible ? I can change my code structure; change external widgets.. (for example widgetB is not yet transpiled,...)
这应该是可能的吗?我可以改变我的代码结构;更改外部小部件..(例如,widgetB 尚未转译,...)
In fact I'm looking for a "plugin system" with an Angular4/webpack application.
事实上,我正在寻找一个带有 Angular4/webpack 应用程序的“插件系统”。
回答by Max Koretskyi
I'm doing exactly the same. And I explain the details in this talkat NgConf.
我正在做完全一样的事情。我在 NgConf 的这次演讲中解释了细节。
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.
首先要了解的是,Webpack 无法在构建时动态加载未知的模块。这是 Webpack 在构建时构建依赖树和收集模块标识符的方式所固有的。这很好,因为 Webpack 是一个模块打包器,而不是模块加载器。所以你需要使用模块加载器,现在唯一可行的选择是 SystemJS。
Then, each plugin should be packaged as a module and all exported components should be added to the entryComponents
of that module.
然后,每个插件都应该打包为一个模块,所有导出的组件都应该添加到该entryComponents
模块的 .
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.
在运行时,您将加载该模块以访问内部声明的组件。您实际上并不需要模块,但它是 Angular 中的一个包装单元,因此您无法避免使用它。现在,一旦您获得一个模块,您必须根据模块是否使用 AOT 构建来进行选择。
If it's built using AOT, you just get the exported factory class from the module and create a module instance:
如果它是使用 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);
}
If it's not built using AOT, you have to compile it using JIT compiler:
如果它不是使用 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);
}
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 中的动态组件的信息