文章目录

Angular 微前端:模块联邦

发布于 2026-04-07 18:27:56 · 浏览 10 次 · 评论 0 条

Angular 微前端:模块联邦

模块联邦允许不同的 JavaScript 应用在运行时动态加载代码,无需将所有代码打包到同一个文件中。这意味着你可以将一个巨大的 Angular 单体应用拆分为多个独立开发、独立部署的小型应用。本指南将手把手教你使用 Angular 和 Module Federation 实现微前端架构。


准备工作

在开始之前,请确保本地开发环境已经准备就绪。

  1. 打开 终端或命令行工具。
  2. 检查 Node.js 版本,确保版本号在 v14 或以上。输入 命令:
    node -v
  3. 安装 Angular CLI(如果尚未安装)。输入 命令:
    npm install -g @angular/cli

创建远程应用

远程应用是提供功能模块的一方,它将被宿主应用加载。

  1. 创建 一个新的 Angular 工程。输入 命令:

    ng new mfe1 --routing --style=scss

    选择 No 当询问是否添加 Server-Side Rendering (SSR) 时(为了简化配置)。

  2. 进入 项目目录:

    cd mfe1
  3. 安装 @angular-architects/module-federation 插件。这是目前配置 Angular 模块联邦最快捷的工具。输入 命令:

    ng add @angular-architects/module-federation --project mfe1 --port 4201

    系统会提示你配置类型,输入 remote 并按下回车。

  4. 创建 一个待导出的组件。输入 命令:

    ng generate component components/ticket
  5. 打开 projects/mfe1/src/app/components/ticket/ticket.component.html 文件。替换 其中的内容为以下代码,以便识别:

    <p style="border: 2px solid blue; padding: 10px;">
      mfe1 Ticket Component Works!
    </p>
  6. 配置 该组件为导出模块。打开 projects/mfe1/src/app/ticket.module.ts(如果没有该文件,请创建它)。写入 以下内容:

    import { NgModule } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { TicketComponent } from './components/ticket/ticket.component';
    
    @NgModule({
      declarations: [
        TicketComponent
      ],
      imports: [
        CommonModule
      ],
      exports: [
        TicketComponent
      ]
    })
    export class TicketModule { }
  7. 修改 模块联邦配置文件。打开 projects/mfe1/webpack.config.js找到 remotes 配置项。确认 配置如下(插件通常已自动生成,但需核对):

    const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
    
    module.exports = {
      // ... 其他配置
      plugins: [
        new ModuleFederationPlugin({
          name: "mfe1",
          filename: "remoteEntry.js",
          exposes: {
            "./TicketModule": "./projects/mfe1/src/app/ticket.module.ts",
          },
          shared: {
            "@angular/core": { singleton: true, strictVersion: true },
            "@angular/common": { singleton: true, strictVersion: true },
            "@angular/router": { singleton: true, strictVersion: true },
          },
        }),
      ],
    };

创建宿主应用

宿主应用是加载并展示远程应用的主程序。

  1. 回到 上级目录。创建 另一个 Angular 工程:

    cd ..
    ng new shell --routing --style=scss

    同样选择 No 针对 SSR。

  2. 进入 宿主项目目录:

    cd shell
  3. 安装 模块联邦插件。输入 命令:

    ng add @angular-architects/module-federation --project shell --port 4200

    输入 host 并按下回车。

  4. 修改 联邦配置以指向远程应用。打开 projects/shell/webpack.config.js找到 remotes 部分。修改 配置如下:

    const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
    
    module.exports = {
      // ... 其他配置
      plugins: [
        new ModuleFederationPlugin({
          name: "shell",
          remotes: {
            mfe1: "http://localhost:4201/remoteEntry.js",
          },
          shared: {
            "@angular/core": { singleton: true, strictVersion: true },
            "@angular/common": { singleton: true, strictVersion: true },
            "@angular/router": { singleton: true, strictVersion: true },
          },
        }),
      ],
    };

路由与加载配置

在宿主应用中配置路由,使其能够动态加载远程模块。

  1. 打开 projects/shell/src/app/app.routes.ts清空 默认内容并写入 以下代码:

    import { Routes } from '@angular/router';
    
    const routes: Routes = [
      {
        path: 'tickets',
        loadChildren: () => import('mfe1/TicketModule').then(m => m.TicketModule)
      }
    ];
    
    export default routes;
  2. 修改 主应用组件模板以添加导航链接。打开 projects/shell/src/app/app.component.html替换 内容为:

    <div style="text-align: center; margin-top: 50px;">
      <h1>Shell Application</h1>
      <nav>
        <a routerLink="/tickets" style="margin: 10px; display: inline-block;">Load MFE1 Tickets</a>
      </nav>
      <router-outlet></router-outlet>
    </div>
  3. 为了让 TypeScript 能够识别 mfe1/TicketModule 这种导入语法,需要配置类型声明。打开 projects/shell/src/decl.d.ts(如果不存在,请在 src 目录下创建此文件)。添加 以下内容:

    declare module 'mfe1/TicketModule';

运行与验证

现在,启动两个应用并验证微前端架构是否正常工作。

  1. 打开 两个独立的终端窗口。

  2. 在第一个终端中,进入 远程应用目录并启动 服务:

    cd /path/to/mfe1
    ng serve

    服务将运行在 http://localhost:4201/。等待编译完成,看到 remoteEntry.js 生成。

  3. 在第二个终端中,进入 宿主应用目录并启动 服务:

    cd /path/to/shell
    ng serve

    服务将运行在 http://localhost:4200/

  4. 打开 浏览器,访问 http://localhost:4200/

  5. 点击 页面上的 "Load MFE1 Tickets" 链接。

  6. 检查 页面内容。你应该能看到带有蓝色边框的文字 "mfe1 Ticket Component Works!"。


架构原理图解

以下流程图描述了宿主应用如何通过 Module Federation 加载远程应用模块的过程:

graph LR User[用户浏览器] -->|访问 Shell App| Shell[Host App: Port 4200] Shell -->|发起 HTTP 请求| Remote[Remote App: Port 4201] Remote -->|返回 remoteEntry.js| Shell Shell -->|动态加载| Ticket[TicketModule] Ticket -->|渲染组件| User

常见问题处理

本地开发跨域错误 (CORS)

如果在宿主应用控制台看到跨域报错,通常是因为浏览器安全策略限制。

  1. 打开 projects/shell/angular.json
  2. 找到 serve -> options 配置项。
  3. 添加修改 headers 配置:
    "headers": {
      "Access-Control-Allow-Origin": "*"
    }

    注意:这只是本地开发的一种快速解决方案,生产环境应在反向代理层(如 Nginx)处理。

共享依赖版本冲突

如果远程应用和宿主应用使用了不同版本的 Angular 或 RxJS,可能会导致运行时错误。

  1. 打开 webpack.config.js
  2. 检查 shared 配置。
  3. 设置 strictVersion: true 可以确保版本严格一致,但可能会阻止加载。如果遇到问题,尝试改为 strictVersion: false 或设置 requiredVersion: "auto" 以允许较小的版本差异。

端口占用

确保 4200 和 4201 端口未被其他程序占用。如需更改端口,请修改 angular.json 中的 serve.options.port 或在启动命令中添加 --port 参数,并同步更新 webpack.config.js 中的 remotes URL 地址。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文