You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular中通过Native Federation动态加载远程组件并使用其选择器?

问题描述

我有一个运行在端口4202的微前端(products仓库),该仓库的联邦配置文件federation.config.js如下:

const { withNativeFederation, shareAll } = require('@angular-architects/native-federation/config');

module.exports = withNativeFederation({
  name: 'mfe2',
  exposes: {
    './SelectorLoaded': './src/app/selector-loaded/selector-loaded.component.ts',
    // other exposed components
  },
  // additional configuration
});

我希望从mfe2动态加载SelectorLoaded组件,在宿主应用的父组件中直接使用其选择器,并无缝向该组件传递输入、接收其输出。

为此我实现了如下方法:

loadMicroFrontend3() {
  loadRemoteModule('mfe2', './SelectorLoaded')
    .then((MicroModule: any) => {
      const ce = createCustomElement(MicroModule.SelectorLoadedComponent, {
        injector: this.injector,
      });

      if (!customElements.get('app-selector-loaded')) {
        customElements.define('app-selector-loaded', ce);
      }
    })
    .catch((err: any) => console.error('Error loading microfrontend:', err));
}

但该方法无效,尽管我可以通过如下路由配置成功加载并渲染SelectorLoaded组件:

{
  path: 'stepper',
  loadComponent: () =>
    loadRemoteModule('mfe2', './SelectorLoaded').then((m) => m.SelectorLoadedComponent),
}
// federation.manifest.json
{
  "mfe1": "http://localhost:4201/remoteEntry.json",
  "mfe2": "http://localhost:4202/remoteEntry.json"
}

我无法在宿主应用的组件中使用SelectorLoadedComponent的选择器(如<app-selector-loaded></app-selector-loaded>)。此前我通过Module Federation实现了该功能,但Native Federation下无法实现。

我的问题:

  1. 是否可通过Native Federation动态加载暴露的微前端组件,实现以下需求:
    • 在宿主应用中直接使用其选择器?
    • 像本地Angular组件一样传递输入、监听输出?
  2. 若不可行,Native Federation下实现该功能的推荐方式是什么?
回答

问题1解答:可以实现,但当前方式存在适配问题

Native Federation支持动态加载组件并通过选择器使用,同时支持输入输出传递,但你用createCustomElement的方式不匹配Native Federation的组件暴露逻辑——它暴露的是Angular组件类,而createCustomElement面向Web Component规范,直接转换会因依赖共享、模块上下文冲突失效。

要实现目标需求,需调整加载逻辑,确保组件被正确注册到宿主的Angular运行环境中:

实现方案1:通过容器动态挂载组件(推荐)

不用转成Web Component,直接通过ViewContainerRef创建远程组件实例,同时传递输入、监听输出:

import { Component, ViewChild, ViewContainerRef, Injector } from '@angular/core';
import { loadRemoteModule } from '@angular-architects/native-federation';

@Component({
  selector: 'app-host-parent',
  template: `
    <button (click)="loadMicroFrontend3()">加载组件</button>
    <div #componentContainer></div>
  `
})
export class HostParentComponent {
  @ViewChild('componentContainer', { read: ViewContainerRef }) container!: ViewContainerRef;

  constructor(private injector: Injector) {}

  async loadMicroFrontend3() {
    try {
      const remoteModule = await loadRemoteModule('mfe2', './SelectorLoaded');
      const ComponentClass = remoteModule.SelectorLoadedComponent;

      // 创建组件实例并挂载到容器
      const componentRef = this.container.createComponent(ComponentClass, {
        injector: this.injector
      });

      // 传递输入属性
      componentRef.instance.yourInputProp = '测试输入值';
      // 监听输出事件
      componentRef.instance.yourOutputEvent.subscribe((data: any) => {
        console.log('收到子组件输出:', data);
      });
    } catch (err) {
      console.error('加载微前端失败:', err);
    }
  }
}

实现方案2:动态注册组件以直接使用选择器

若要在模板中直接写<app-selector-loaded>,需动态创建NgModule并注册远程组件:

import { NgModule, Compiler } from '@angular/core';
import { loadRemoteModule } from '@angular-architects/native-federation';

constructor(private compiler: Compiler, private injector: Injector) {}

async loadAndRegisterComponent() {
  const remoteModule = await loadRemoteModule('mfe2', './SelectorLoaded');
  const ComponentClass = remoteModule.SelectorLoadedComponent;

  // 动态创建包含该组件的模块
  const dynamicModule = NgModule({
    declarations: [ComponentClass],
    exports: [ComponentClass]
  })(class {});

  // 编译并加载模块
  const moduleFactory = await this.compiler.compileModuleAsync(dynamicModule);
  moduleFactory.create(this.injector);

  // 此时可在模板中直接使用<app-selector-loaded>标签
}

注意:这种方式要求宿主与远程应用的Angular版本、共享依赖完全兼容,否则会出现编译或运行时错误。

问题2解答:Native Federation的推荐方式

如果上述动态注册方式觉得复杂,官方推荐两种更稳定的集成方案:

  1. 路由级加载:即你已实现的通过loadComponent在路由中加载组件,适合页面级的微前端集成,无需额外处理输入输出,路由参数可通过激活路由传递。
  2. 容器式组件加载:即上述方案1的方式,通过ViewContainerRef动态挂载组件,既能满足在父组件中直接使用的需求,又能无缝传递输入输出,是组件级集成的最优方案。

不推荐用Web Component封装Native Federation组件,两者的依赖注入、变更检测机制存在冲突,容易引发难以排查的问题。

内容的提问来源于stack exchange,提问作者mideo mideo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 12:59:50