基于Module Federation的Angular微前端:远程模块并排展示及路由需求
解决方案:Angular Module Federation 微前端并排展示与独立路由实现
一、实现远程模块并排展示
要在壳应用中横向并排展示Mfe1和Mfe2的模块,核心是通过布局容器承载动态加载的远程组件:
- 确认壳应用的远程模块配置
确保壳应用的webpack.config.js已正确注册远程模块:
// shell webpack.config.js module.exports = { plugins: [ new ModuleFederationPlugin({ name: 'shell', remotes: { mfe1: 'mfe1@http://localhost:3001/remoteEntry.js', mfe2: 'mfe2@http://localhost:3002/remoteEntry.js' } }) ] };
- 用Flex布局搭建并排容器
在壳应用的宿主组件模板(如app.component.html)中创建弹性布局容器,为每个微前端预留占位:
<!-- app.component.html --> <div class="mfe-grid"> <div class="mfe-card"> <ng-template #mfe1Host></ng-template> </div> <div class="mfe-card"> <ng-template #mfe2Host></ng-template> </div> </div>
配套CSS实现并排布局:
.mfe-grid { display: flex; gap: 24px; padding: 24px; flex-wrap: wrap; } .mfe-card { flex: 1; min-width: 400px; border: 1px solid #e0e0e0; border-radius: 8px; padding: 16px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
- 动态加载远程组件到占位容器
在宿主组件类中,通过loadRemoteModule将远程组件渲染到对应占位:
// app.component.ts import { Component, ViewChild, ViewContainerRef, OnInit } from '@angular/core'; import { loadRemoteModule } from '@angular-architects/module-federation'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { @ViewChild('mfe1Host', { read: ViewContainerRef }) mfe1Host!: ViewContainerRef; @ViewChild('mfe2Host', { read: ViewContainerRef }) mfe2Host!: ViewContainerRef; async ngOnInit() { // 加载Mfe1主组件 const mfe1Module = await loadRemoteModule({ remoteName: 'mfe1', exposedModule: './MainComponent' }); this.mfe1Host.createComponent(mfe1Module.Mfe1MainComponent); // 加载Mfe2主组件 const mfe2Module = await loadRemoteModule({ remoteName: 'mfe2', exposedModule: './MainComponent' }); this.mfe2Host.createComponent(mfe2Module.Mfe2MainComponent); } }
二、实现远程模块的独立路由导航
要让微前端内的列表→详情导航不影响壳应用路由,可通过路由前缀隔离或组件内独立路由实现:
方案1:路由前缀隔离(推荐)
给每个微前端分配专属路由前缀,壳应用仅作为路由分发入口:
- 壳应用配置路由占位
在壳应用的app-routing.module.ts中,为每个微前端配置路由入口,加载远程路由模块:
// app-routing.module.ts import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { loadRemoteModule } from '@angular-architects/module-federation'; const routes: Routes = [ { path: 'mfe1', loadChildren: () => loadRemoteModule({ remoteName: 'mfe1', exposedModule: './RoutingModule' }).then(m => m.Mfe1RoutingModule) }, { path: 'mfe2', loadChildren: () => loadRemoteModule({ remoteName: 'mfe2', exposedModule: './RoutingModule' }).then(m => m.Mfe2RoutingModule) }, { path: '', redirectTo: '/mfe1', pathMatch: 'full' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
- 微前端内部配置子路由
在Mfe1的mfe1-routing.module.ts中,配置自身的列表、详情路由(无需前缀):
// mfe1-routing.module.ts import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { Mfe1ListComponent } from './list/list.component'; import { Mfe1DetailComponent } from './detail/detail.component'; const routes: Routes = [ { path: '', component: Mfe1ListComponent }, { path: 'detail/:id', component: Mfe1DetailComponent } ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class Mfe1RoutingModule { }
此时Mfe1的导航路径为/mfe1/detail/1,Mfe2为/mfe2/detail/2,完全独立于壳应用路由,互不干扰。
方案2:组件内独立路由(无URL变化)
若无需修改URL,可通过组件状态传递实现导航:
// mfe1-list.component.ts import { Component } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { Mfe1DetailComponent } from '../detail/detail.component'; @Component({ selector: 'app-mfe1-list', templateUrl: './list.component.html' }) export class Mfe1ListComponent { constructor(private dialog: MatDialog) {} openDetail(id: number) { // 通过弹窗展示详情,不修改路由 this.dialog.open(Mfe1DetailComponent, { data: { id }, width: '600px' }); } }
关键配置检查
确保微前端的webpack.config.js正确暴露路由模块:
// mfe1 webpack.config.js module.exports = { plugins: [ new ModuleFederationPlugin({ name: 'mfe1', filename: 'remoteEntry.js', exposes: { './MainComponent': './src/app/main/main.component.ts', './RoutingModule': './src/app/mfe1-routing.module.ts' } }) ] };
内容的提问来源于stack exchange,提问作者tech savy
相关产品推荐
相关产品推荐

