欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 游戏 > 微前端 - Native Federation使用完整示例

微前端 - Native Federation使用完整示例

2025/6/9 23:24:04 来源:https://blog.csdn.net/qq_44327851/article/details/148493612  浏览:    关键词:微前端 - Native Federation使用完整示例

       这是一个极简化的 Angular 使用@angular-architects/native-federation 插件的微前端示例,只包含一个主应用和一个远程应用。

完整示例展示

项目结构

federation-simple/
├── host-app/      # 主应用
└── remote-app/    # 远程应用

创建远程应用 (remote-app)

 初始化项目
ng new remote-app --standalone --minimal --style=css --routing=false
cd remote-app
npm install @angular-architects/native-federation --save-dev
配置 Native Federation
ng add @angular-architects/native-federation --project remote-app --port 4201
创建远程组件

编辑 src/app/hello.component.ts:

import { Component } from '@angular/core';@Component({standalone: true,template: `<div style="border: 2px solid blue;padding: 20px;margin: 10px;border-radius: 5px;"><h2>Hello from Remote App!</h2><p>This component is loaded from the remote app</p></div>`
})
export class HelloComponent {}
配置暴露的模块

编辑 federation.config.js:

module.exports = {name: 'remoteApp',exposes: {'./Hello': './src/app/hello.component.ts'},shared: {'@angular/core': { singleton: true, strictVersion: true },'@angular/common': { singleton: true, strictVersion: true },'rxjs': { singleton: true, strictVersion: true }}
};

创建主应用 (host-app)

初始化项目
ng new host-app --standalone --minimal --style=css --routing=true
cd host-app
npm install @angular-architects/native-federation @angular-architects/module-federation-tools --save-dev
配置 Native Federation
ng add @angular-architects/native-federation --project host-app --port 4200
创建主页面

编辑 src/app/app.component.ts:

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';@Component({standalone: true,imports: [CommonModule, RouterOutlet],template: `<div style="padding: 20px;"><h1>Host Application</h1><nav><a routerLink="/" style="margin-right: 15px;">Home</a><a routerLink="/remote">Load Remote Component</a></nav><router-outlet></router-outlet></div>`
})
export class AppComponent {}
创建远程组件加载页面

创建 src/app/remote.component.ts:

在这里使用了<app-remote-hello> 那这个怎么来的呢?请见下面的关键点说明第四点!!!

import { Component, OnInit } from '@angular/core';
import { loadRemoteModule } from '@angular-architects/module-federation';@Component({standalone: true,template: `<div style="margin-top: 20px;"><h2>Remote Component</h2><div *ngIf="loading">Loading remote component...</div><div *ngIf="error" style="color: red;">Failed to load remote component: {{error}}</div><ng-container *ngIf="!loading && !error"><app-remote-hello></app-remote-hello></ng-container></div>`
})
export class RemoteComponent implements OnInit {loading = true;error: string | null = null;async ngOnInit() {try {await loadRemoteModule({remoteEntry: 'http://localhost:4201/remoteEntry.js',remoteName: 'remoteApp',exposedModule: './Hello'});this.loading = false;} catch (err) {this.error = err instanceof Error ? err.message : String(err);this.loading = false;}}
}
配置路由

编辑 src/app/app.routes.ts:

import { Routes } from '@angular/router';
import { RemoteComponent } from './remote.component';export const APP_ROUTES: Routes = [{ path: 'remote', component: RemoteComponent,providers: [// 注册远程组件{provide: 'remote-hello',useValue: {remoteEntry: 'http://localhost:4201/remoteEntry.js',remoteName: 'remoteApp',exposedModule: './Hello',componentName: 'Hello'}}]},{ path: '**', redirectTo: 'remote' }
];
配置应用

编辑 src/app/app.config.ts:

import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideRouter } from '@angular/router';
import { APP_ROUTES } from './app.routes';
import { RemoteComponent } from '@angular-architects/module-federation-tools';export const appConfig: ApplicationConfig = {providers: [provideRouter(APP_ROUTES),importProvidersFrom(RemoteComponent.forRemote({type: 'module',remoteEntry: 'http://localhost:4201/remoteEntry.js',exposedModule: './Hello',componentName: 'Hello'}))]
};
配置 federation

编辑 federation.config.js: 

module.exports = {name: 'hostApp',remotes: {'remoteApp': 'http://localhost:4201/remoteEntry.js'},shared: {'@angular/core': { singleton: true, strictVersion: true },'@angular/common': { singleton: true, strictVersion: true },'@angular/router': { singleton: true, strictVersion: true },'rxjs': { singleton: true, strictVersion: true }}
};

运行应用

  1. 打开两个终端窗口
  2. 在第一个终端中运行远程应用
  3. 在第二个终端中运行主应用
  4. 访问应用
  5. 在主应用中,点击 "Load Remote Component" 链接将加载并显示远程组件

关键点说明

项目简单说明下面三点:

  1. 远程应用: remote中暴露一个了简单的HelloCompoent并且配置了共享的 Angular 核心库;

  2. 主应用: host中使用 了loadRemoteModule动态加载远程组件,同时通过路由导航到远程组件,并且配置了远程模块的引用;

  3. 共享依赖: remote项目和Host项目Angular 核心库和 RxJS 被标记为共享单例,并且确保了版本兼容性

  4. <app-remote-hello> 这个selector怎么来的

app-remote-hello 是自定义元素,通过下面的方式创建和使用的:

组件名称的生成规则: 当使用 @angular-architects/module-federation-tools 的 RemoteComponent时,组件名称会自动按照以下规则生成:

app-remote-<componentName>
  • app 是 Angular 默认的前缀
  • remote 表示这是一个远程组件
  • <componentName> 是你在配置中指定的组件名称(这里是 hello

具体配置来源:在示例中,这个名称来源于下面几个地方的配置:

在 app.config.ts 中:

importProvidersFrom(RemoteComponent.forRemote({type: 'module',remoteEntry: 'http://localhost:4201/remoteEntry.js',exposedModule: './Hello',componentName: 'Hello'  // ← 这里定义了基础名称})
)

在 remote.component.ts 中:

<app-remote-hello></app-remote-hello>

完整的名称转换过程:

  • 你配置了 componentName: Hello
  • 系统会自动转换为小写形式:hello
  • 加上前缀 app-remote- 形成最终标签名:app-remote-hello

如何自定义这个名称:如果想使用不同的标签名,可以这样修改

// 在 app.config.ts 中
RemoteComponent.forRemote({// ...其他配置componentName: 'MyCustomHello',  // 自定义名称elementName: 'my-hello-element'  // 自定义元素名(可选)
})// 然后在模板中使用
<my-hello-element></my-hello-element>

为什么能这样使用:这是因为 @angular-architects/module-federation-tools 在底层做了以下工作:

  • 动态注册了一个新的 Angular 组件

  • 将该组件定义为自定义元素(Custom Element)

  • 自动处理了组件名称的转换

  • 设置了与远程组件的连接

验证方法:如果你想确认这个组件是如何被注册的,可以在浏览器开发者工具中:

  • 打开 Elements 面板

  • 找到 <app-remote-hello> 元素

  • 查看它的属性,会发现它是一个 Angular组件

    • Angular 组件会有特殊属性

      • 查看是否有 _nghost-* 和 _ngcontent-* 这类 Angular 特有的属性

      • 例如:<app-remote-hello _ngcontent-abc="" _nghost-def="">

    • 检查自定义元素定义

      • 在 Console 中输入:document.querySelector('app-remote-hello').constructor.name

      • 如果是 Angular 组件,通常会显示 HTMLElement(因为 Angular 组件最终是自定义元素)

 参考资料:

核心资源

  1. @angular-architects/native-federation 官方文档
    📖 GitHub 仓库 & 文档

    • 包含安装指南、配置选项和基本用法

  2. Module Federation 概念解释
    📖 Webpack 官方文档

    • 理解微前端的核心机制


教程文章

  1. Angular 微前端完整指南
    📖 Angular Architects 博客

    • 含代码示例和架构图

  2. 实战案例分步教程
    📖 Dev.to 详细教程

    • 从零开始的实现步骤


视频资源

  1. 官方演示视频
    ▶️ YouTube 教程

    • 30分钟实战演示(Angular团队录制)

  2. 模块联邦深度解析
    ▶️ Webpack 官方频道

    • 底层原理讲解


扩展工具

  1. 模块联邦工具库
    📦 npm @angular-architects/module-federation-tools
    • 简化动态加载的工具

  2. 微前端状态管理方案
    📖 NgRx 集成指南
    • 跨应用状态管理建议


常见问题

  1. 共享依赖解决方案
    ❓ Stack Overflow 热门讨论

    • 版本冲突处理方案

  2. 生产环境部署指南
    📖 Angular 部署文档

    • 包含微前端部署注意事项


示例代码库

  1. 官方示例项目:可直接运行的完整项目
    💻 GitHub 代码库

    版权声明:

    本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

    我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

    热搜词