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

Angular模块联邦中如何无需刷新窗口更新远程模块

动态模块联邦:无需刷新页面更新模块状态

我正在实现动态模块联邦架构,包含一个宿主应用和多个远程应用。目前遇到的问题是:启动所有应用(包括宿主)后,停止其中一个远程应用,此时导航到该远程应用的路由时,仍然会显示之前加载过的模块内容。我需要实现无需刷新页面就能动态感知远程应用状态变化并更新模块的功能。


宿主应用 app.routes.ts 代码

import { loadRemoteModule } from '@angular-architects/module-federation';
import { Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { NotFoundComponent } from './not-found/not-found.component';

export const APP_ROUTES: Routes = [
  {
    path: '',
    // component: HomeComponent,
    pathMatch: 'full',
    redirectTo: 'cli-commands',
  },

  {
    path: 'log-collection',
    loadChildren: () =>
      loadRemoteModule({
        type: 'manifest',
        remoteName: 'log-collection',
        exposedModule: './Module',
      })
        .then((m) => m.LogCollectionModule)
        .catch((err) => {
          return import('./not-found/not-found.module').then((m) => m.NotFoundModule);
        }),
  },
 
  {
    path: 'encrypt',
    loadChildren: () =>
      loadRemoteModule({
        type: 'manifest',
        remoteName: 'encrypt',
        exposedModule: './Module',
      })
        .then((m) => m.EncryptModule)
        .catch((err) => {
          console.log(err);
          
          return import('./not-found/not-found.module').then((m) => m.NotFoundModule);
        }),
  },
  
  {
    path: 'audit-trail',
    loadChildren: () =>
      loadRemoteModule({
        type: 'manifest',
        remoteName: 'audit-trail',
        exposedModule: './Module',
      })
        .then((m) => m.AuditTrailModule)
        .catch((err) => {
          return import('./not-found/not-found.module').then((m) => m.NotFoundModule);
        }),
    data: { remoteEntry: 'http://localhost:4207/remoteEntry.js' }
  },
  {
    path: 'not-found',
    component: NotFoundComponent,
  },
  {
    path: '**',
    component: NotFoundComponent,
  },
];

宿主应用 webpack.config.ts 代码

const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const { MFLiveReloadPlugin } = require("@module-federation/fmr");

const sharedMappings = new mf.SharedMappings();
sharedMappings.register(path.join(__dirname, "../../tsconfig.json"), [
  /* 要共享的映射路径 */
 
]);
console.log(path.resolve(__dirname, '..'));
module.exports = {
  output: {
    uniqueName: "shell-rcm",
    publicPath: 'auto',
  },
  optimization: {
    // 仅用于绕过临时bug
    runtimeChunk: false,
  },
  devServer: {
    liveReload: true,
    watchFiles: [path.resolve(__dirname, '..', 'src/app')], // 确保指向宿主应用文件夹
  },
  plugins: [
    new MFLiveReloadPlugin({
      port: 4200, // 应用运行的端口
      container: "shell-rcm", // 应用名称,必须唯一
      standalone: false, // false表示使用Chrome扩展
    }),
    new ModuleFederationPlugin({
      shared: {
        "@angular/core": { singleton: true, strictVersion: true },
        "@angular/common": { singleton: true, strictVersion: true },
        "@angular/router": { singleton: true, strictVersion: true },
        "@angular/material": { singleton: true, strictVersion: true },
        "ngx-toastr": { singleton: true, strictVersion: true },
        // "keycloak-angular": { singleton: true, strictVersion: true, eager: true },

        ...sharedMappings.getDescriptors(),
      },
    }),
    sharedMappings.getPlugin(),
  ],
};

解决方案

1. 清除模块缓存

模块联邦默认会缓存已加载的远程模块,即使远程应用停止,缓存依然存在。每次导航前清除对应模块的缓存,强制重新检测远程应用状态:

// 导入clearRemoteModuleCache方法
import { loadRemoteModule, clearRemoteModuleCache } from '@angular-architects/module-federation';

// 修改log-collection路由示例
{
  path: 'log-collection',
  loadChildren: () => {
    // 清除目标远程模块的缓存
    clearRemoteModuleCache('log-collection');
    return loadRemoteModule({
      type: 'manifest',
      remoteName: 'log-collection',
      exposedModule: './Module',
    })
      .then((m) => m.LogCollectionModule)
      .catch((err) => {
        return import('./not-found/not-found.module').then((m) => m.NotFoundModule);
      });
  },
},

2. 增加远程应用可用性检测

在加载模块前主动检测远程应用是否可达,确保只在应用可用时加载模块:

// 封装可用性检测函数
async function checkRemoteAvailability(remoteEntryUrl: string): Promise<boolean> {
  try {
    const response = await fetch(remoteEntryUrl, { method: 'HEAD' });
    return response.ok;
  } catch {
    return false;
  }
}

// 修改audit-trail路由示例
{
  path: 'audit-trail',
  loadChildren: async () => {
    const remoteEntryUrl = 'http://localhost:4207/remoteEntry.js';
    const isAvailable = await checkRemoteAvailability(remoteEntryUrl);
    
    if (!isAvailable) {
      clearRemoteModuleCache('audit-trail');
      return import('./not-found/not-found.module').then((m) => m.NotFoundModule);
    }
    
    return loadRemoteModule({
      type: 'manifest',
      remoteName: 'audit-trail',
      exposedModule: './Module',
    })
      .then((m) => m.AuditTrailModule)
      .catch((err) => {
        return import('./not-found/not-found.module').then((m) => m.NotFoundModule);
      });
  },
  data: { remoteEntry: 'http://localhost:4207/remoteEntry.js' }
},

3. 统一错误处理逻辑

结合缓存清除与可用性检测,确保无论远程应用状态如何变化,导航时都能获取最新状态,避免缓存内容干扰。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:59:59