如何通过Module Federation在Angular中动态加载远程组件并本地使用
实现方案
步骤1:配置主应用的Module Federation
先在主应用的Module Federation配置中添加远程应用app1的映射,替换为你实际的子应用部署地址:
new ModuleFederationPlugin({ name: "host", remotes: { app1: "app1@http://localhost:4201/app1.js", }, shared: { "@angular/core": { singleton: true, strictVersion: true }, "@angular/common": { singleton: true, strictVersion: true }, "@angular/router": { singleton: true, strictVersion: true }, } })
步骤2:修改AppModule配置
导入必要依赖,加载远程组件并注册为自定义元素,同时添加自定义元素识别规则:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA, Injector } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { createCustomElement } from '@angular/elements'; import { loadRemoteModule } from '@angular-architects/module-federation'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent], // 允许Angular识别非本地注册的自定义标签 schemas: [CUSTOM_ELEMENTS_SCHEMA] }) export class AppModule { constructor(private injector: Injector) { // 应用启动时加载远程Heroes组件,注册为原生自定义元素 loadRemoteModule({ remoteEntry: 'http://localhost:4201/app1.js', remoteName: 'app1', exposedModule: './Heroes' }).then(remoteModule => { const HeroesElement = createCustomElement(remoteModule.HeroesComponent, { injector: this.injector }); // 注册到浏览器自定义元素注册表,标签名和组件selector保持一致 customElements.define('app-heroes', HeroesElement); }) } }
步骤3:直接使用组件
配置完成后,即可在主应用任意模板中直接使用<app-heroes></app-heroes>标签,使用体验和本地组件完全一致。
可选方案:封装本地代理组件(无需全局注册)
如果不需要全局使用该组件,可以创建本地代理组件动态加载远程组件,无需注册自定义元素:
// heroes-wrapper.component.ts import { Component, ViewChild, ViewContainerRef, OnInit } from '@angular/core'; import { loadRemoteModule } from '@angular-architects/module-federation'; @Component({ selector: 'app-heroes', template: `<ng-template #container></ng-template>` }) export class HeroesWrapperComponent implements OnInit { @ViewChild('container', { read: ViewContainerRef }) container!: ViewContainerRef; async ngOnInit() { const remoteModule = await loadRemoteModule({ remoteEntry: 'http://localhost:4201/app1.js', remoteName: 'app1', exposedModule: './Heroes' }); this.container.createComponent(remoteModule.HeroesComponent); } }
将该代理组件加入AppModule的declarations数组即可,同样可以直接使用<app-heroes></app-heroes>标签。
注意事项
- 主应用和远程应用的Angular核心依赖版本尽量保持一致,避免运行时冲突
- 若远程组件使用了其他Angular指令(如*ngIf、*ngFor等),需要确保依赖的CommonModule等模块在shared配置中被标记为单例,或者远程组件使用standalone配置自行导入依赖。
内容的提问来源于stack exchange,提问作者Phate
相关产品推荐
相关产品推荐

