使用 AWS Amplify、Angular 和 Module Federation 为微前端创建门户 - AWS Prescriptive Guidance

使用 AWS Amplify、Angular 和 Module Federation 为微前端创建门户

Milena Godau 和 Pedro Garcia,Amazon Web Services

摘要

通过微前端架构,多个团队能够独立处理前端应用程序的不同部分。每个团队都可以开发、构建和部署前端的某个片段,而不会干扰应用程序的其他部分。从最终用户的角度来看,它似乎就是一个单一的、有凝聚力的应用程序。但是,他们正在与由不同团队发布的多个独立应用程序进行交互。

本文档介绍了如何使用 AWS AmplifyAngular 前端框架和 Module Federation 来创建微前端架构。在此模式中,微前端通过 Shell(或)应用程序在客户端进行组合。Shell 应用程序可充当检索、显示和集成微前端的容器。Shell 应用程序可处理全局路由,以便加载不同的微前端。@angular-architects/module-federation 插件可将 Module Federation 与 Angular 集成。您可以通过使用 AWS Amplify 部署 Shell 应用程序和微前端。最终用户可通过基于 Web 的门户访问应用程序。

该门户是垂直拆分的。这意味着这些微前端是整个视图或视图组,而不是同一视图的一部分。因此,Shell 应用程序一次只能加载一个微前端。

微前端是以远程模块的形式实施的。Shell 应用程序会延迟加载这些远程模块,因此将微前端初始化推迟到需要时再执行。这种方法通过仅加载必要的模块来优化应用程序性能。这就可以减少初始加载时间,并改善整体用户体验。此外,您可以通过 webpack 配置文件(webpack.config.js),跨模块共享常见的依赖项。这种做法可以促进代码重复使用,减少重复并简化捆绑过程。

先决条件和限制

先决条件

产品版本

  • Angular CLI 版本 13.1.2 或更高版本

  • @angular-architects/module-federation 版本 14.0.1 或更高版本

  • webpack 版本 5.4.0 或更高版本

  • AWS Amplify Gen 1

限制

微前端架构是一种构建具有弹性的可扩展 Web 应用程序的强大方法。但是,在采用这种方法之前,请务必了解以下潜在挑战:

  • 集成 – 与整体式前端相比,其中一个关键挑战是复杂性可能会增加。编排多个微前端、处理它们之间的通信以及管理共享依赖项可能会更加复杂。此外,微前端之间的通信可能会产生性能开销。这种通信会增加延迟并降低性能。这一问题需要通过高效消息收发机制和数据共享策略来解决。

  • 代码重复 – 由于每个微前端都是独立开发的,因此通用功能或共享库可能存在代码重复风险。这可能会增加应用程序的总体大小,并带来维护挑战。

  • 协调和管理 – 跨多个微前端协调开发和部署流程可能具有挑战性。在分布式架构中,确保版本控制一致、管理依赖项以及维护组件之间的兼容性变得更为重要。建立明确的治理、指导原则以及自动测试和部署管道,对于实现无缝协作和交付至关重要。

  • 测试 – 测试微前端架构可能比测试整体式前端更为复杂。要执行跨组件集成测试和端到端测试,并验证跨多个微前端的一致用户体验,需要付出额外的努力以及专门的测试策略。

在承诺使用微前端方法之前,我们建议您先查看了解和实施 AWS 上的微前端

架构

在微前端架构中,每个团队都可独立开发和部署功能。下图显示了多个 DevOps 团队如何协同工作。门户团队开发 Shell 应用程序。Shell 应用程序则可充当容器,检索、显示和集成其他 DevOps 团队发布的微前端应用程序。您使用 AWS Amplify 来发布 Shell 应用程序和微前端应用程序。

将多个微前端发布到 Shell 应用程序,而用户可通过 Web 门户访问该应用程序。

架构图显示了以下工作流程:

  1. 门户团队开发和维护 Shell 应用程序。Shell 应用程序编排微前端的集成和渲染,从而构成整个门户。

  2. 团队 A 和 B 开发并维护一个或多个集成到门户中的微前端或功能。每个团队都可以独立处理其各自的微前端。

  3. 最终用户使用 Amazon Cognito 进行身份验证。

  4. 最终用户访问门户,然后加载 Shell 应用程序。当用户导航时,Shell 应用程序会处理路由并检索请求的微前端,加载其捆绑包。

工具

AWS 服务

  • AWS Amplify 是一组专门构建的工具和功能,可帮助前端 Web 和移动开发人员快速地在 AWS 上构建全栈应用程序。在此模式下,您可以使用 Amplify CLI 来部署 Amplify 微前端应用程序。

  • AWS Command Line Interface(AWS CLI)是一款开源工具,可帮助您在命令行 Shell 中通过命令与 AWS 服务进行交互。

其他工具

  • @angular-architects/module-federation 是可将 Angular 与 Module Federation 集成的插件。

  • Angular 是一个开源 Web 应用程序框架,用于构建现代、可扩展且可测试的单页应用程序。它采用了基于组件的模块化架构,可促进代码的重复使用和维护。

  • Node.js 是事件驱动的 JavaScript 运行时环境,专为构建可扩展的网络应用程序而设计。

  • npm 是在 Node.js 环境中运行的软件注册表,用于共享或借用软件包以及管理私有软件包的部署。

  • Webpack Module Federation 可帮助您将独立编译和部署的代码(例如微前端或插件)加载到应用程序中。

代码存储库

此模式的代码可在使用 Angular 和 Module Federation 的微前端门户 GitHub 存储库中获得。此存储库包含以下两个文件夹:

  • shell-app,包含 Shell 应用程序的代码。

  • feature1-app,包含一个示例微前端。Shell 应用程序可获取这个微前端并将其显示为门户应用程序中的一个页面。

最佳实践

微前端架构具有诸多优势,但也会带来复杂性。以下是有助于实现流畅开发、高质量代码和出色用户体验的一些最佳实践:

  • 规划和沟通 – 为了简化协作,请在前期规划、设计和清晰的沟通渠道等方面投入时间和精力。

  • 设计一致性 – 通过使用设计系统、样式指南和组件库,在所有微前端中强制实施一致的视觉风格。这样便能提供连贯的用户体验并加快开发速度。

  • 依赖项管理 – 由于微前端会独立演变发展,因此应采用标准化合同和版本控制策略,以便有效管理依赖项并防止兼容性问题。

  • 微前端架构 – 为了实现独立的开发和部署,每个微前端都应该对封装的功能承担清晰明确的责任。

  • 集成和通信 – 为了促进顺利集成并最大限度地减少冲突,应在微前端之间定义明确的合同和通信协议,包括 API、事件和共享数据模型。

  • 测试和质量保证 – 为微前端实施测试自动化和持续集成管道。这样可以提高整体质量,减少手动测试工作,并验证微前端交互之间的功能。

  • 性能优化 持续监控性能指标并跟踪微前端之间的依赖关系。这可以帮助您识别瓶颈并保持最佳的应用程序性能。为此,请使用性能监控和依赖关系分析工具。

  • 开发人员体验 – 注重开发人员体验,提供清晰的文档、工具和示例。这可以帮助您简化开发流程及吸引新的团队成员。

操作说明

任务描述所需技能

创建 Shell 应用程序。

  1. 在 Angular CLI 中,输入以下命令:

    ng new shell --routing
  2. 输入以下命令,以导航至项目文件夹:

    cd shell
    注意

    Shell 和微前端应用程序的文件夹和项目结构可以完全彼此独立。它们可以作为独立的 Angular 应用程序来进行处理。

应用程序开发人员

安装 插件。

在 Angular CLI 中,输入以下命令,以安装 @angular-architects/module-federation 插件:

ng add @angular-architects/module-federation --project shell --port 4200
应用程序开发人员

将微前端 URL 添加为环境变量。

  1. 打开 environment.ts 文件。

  2. mfe1URL: 'http://localhost:5000' 添加到 environment 对象:

    export const environment = { production: false, mfe1URL: 'http://localhost:5000', };
  3. 保存并关闭 environment.ts 文件。

应用程序开发人员

定义路由。

  1. 打开 app-routing.module.ts 文件。

  2. 在 Angular CLI 中,输入以下命令,以从 @angular-architects/module-federation 插件导入 loadRemoteModule 模块:

    import { loadRemoteModule } from '@angular-architects/module-federation';
  3. 将默认路由设置为以下内容:

    { path: '', pathMatch: 'full', redirectTo: 'mfe1' },
  4. 设置微前端的路由:

    { path: 'mfe1', loadChildren: () => loadRemoteModule({ type: 'module', remoteEntry: `${environment.mfe1URL}/remoteEntry.js`, exposedModule: './Module' }) .then(m => m.Mfe1Module) },
  5. 保存并关闭 app-routing.module.ts 文件。

应用程序开发人员

声明 mfe1 模块。

  1. src 文件夹中,创建一个名为 decl.d.ts 的新文件。

  2. 打开 decl.d.ts 文件。

  3. 将以下内容添加到文件中:

    declare module 'mfe1/Module';
  4. 保持并关闭 decl.d.ts 文件。

应用程序开发人员

准备微前端的预加载。

预加载微前端有助于 webpack 正确协商共享库和程序包。

  1. 打开 main.ts 文件。

  2. 将该内容替换为以下内容:

    import { loadRemoteEntry } from '@angular-architects/module-federation'; Promise.all([ loadRemoteEntry(`${environment.mfe1URL}/remoteEntry.js`, 'mfe1'), ]) .catch(err => console.error('Error loading remote entries', err)) .then(() => import('./bootstrap')) .catch(err => console.error(err));
  3. 保持并关闭 main.ts 文件。

应用程序开发人员

调整 HTML 内容。

  1. 打开 app.component.html 文件。

  2. 将该内容替换为以下内容:

    <h1>Shell application is running!</h1> <router-outlet></router-outlet>
  3. 保存并关闭 app.component.html 文件。

应用程序开发人员
任务描述所需技能

创建微前端。

  1. 在 Angular CLI 中,输入以下命令:

    ng new mfe1 --routing
  2. 输入以下命令,以导航至项目文件夹:

    cd mfe1
应用程序开发人员

安装 插件。

输入以下命令,以安装 @angular-architects/module-federation 插件:

ng add @angular-architects/module-federation --project mfe1 --port 5000
应用程序开发人员

创建模块和组件。

输入以下命令,以创建模块和组件并将其导出为远程条目模块:

ng g module mfe1 --routing ng g c mfe1
应用程序开发人员

设置默认路由路径。

  1. 打开 mfe-routing.module.ts 文件。

  2. 将默认路由设置为以下内容:

    { path: '', component: Mfe1Component },
  3. 保存并关闭 mfe-routing.module.ts 文件。

应用程序开发人员

添加 mfe1 路由。

  1. 打开 app-routing.module.ts 文件。

  2. 将默认路由设置为以下内容:

    { path: '', pathMatch: 'full', redirectTo: 'mfe1' },
  3. 添加以下 mfe1 路由:

    { path: 'mfe1', loadChildren: () => import('./mfe1/mfe1.module').then((m) => m.Mfe1Module), },
  4. 保存并关闭 app-routing.module.ts 文件。

应用程序开发人员

编辑 webpack.config.js 文件。

  1. 打开 webpack.config.js 文件。

  2. 编辑 For remotes 部分以匹配以下内容:

    // For remotes (please adjust) name: "mfe1", filename: "remoteEntry.js", exposes: { './Module': './src/app/mfe1/mfe1.module.ts', },
  3. shared 部分中,添加 mfe1 应用程序与 Shell 应用程序共享的所有依赖项:

    shared: share({ "@angular/core": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, "@angular/common": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, "@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, "@angular/router": { singleton: true, strictVersion: true, requiredVersion: 'auto' }, ...sharedMappings.getDescriptors() })
  4. 保持并关闭 webpack.config.js 文件。

应用程序开发人员

调整 HTML 内容。

  1. 打开 app.component.html 文件。

  2. 将该内容替换为以下内容:

    <router-outlet></router-outlet>
  3. 保存并关闭 app.component.html 文件。

应用程序开发人员
任务描述所需技能

运行 mfe1 应用程序。

  1. 输入以下命令,以启动 mfe1 应用程序:

    npm start
  2. 在 Web 浏览器中,访问 http://localhost:5000

  3. 验证微前端是否可以独立运行。mfe1 应用程序应该能够正确渲染,不会出现任何错误。

应用程序开发人员

运行 Shell 应用程序。

  1. 输入以下命令,以启动 Shell 应用程序:

    npm start
  2. 在 Web 浏览器中,访问 http://localhost:4200/mfe1

  3. 验证 mfe1 微前端是否已嵌入 Shell 应用程序中。门户应用程序应该能够正确渲染,不会出现任何错误,并且 mfe1 应用程序应嵌入其中。

应用程序开发人员
任务描述所需技能

创建模块和组件。

在 Shell 应用程序的根文件夹中,输入以下命令,以创建错误页面的模块和组件:

ng g module error-page --routing ng g c error-page
应用程序开发人员

调整 HTML 内容。

  1. 打开 error-page.component.html 文件。

  2. 将该内容替换为以下内容:

    <p>Sorry, this page is not available.</p>
  3. 保存并关闭 error-page.component.html 文件。

应用程序开发人员

设置默认路由路径。

  1. 打开 error-page-routing.module.ts 文件。

  2. 将默认路由设置为以下内容:

    { path: '', component: ErrorPageComponent },
  3. 保存并关闭 error-page-routing.module.ts 文件。

应用程序开发人员

创建函数以加载微前端。

  1. 打开 app-routing.module.ts 文件。

  2. 创建以下函数:

    function loadMFE(url: string) { return loadRemoteModule({ type: 'module', remoteEntry: `${url}/remoteEntry.js`, exposedModule: './Module' }) .then(m => m.Mfe1Module) .catch( () => import('./error-page/error-page.module').then(m => m.ErrorPageModule) ); }
  3. mfe1 路由修改为以下内容:

    { path: 'mfe1', loadChildren: () => loadMFE(environment.mfe1URL) },
  4. 保存并关闭 app-routing.module.ts 文件。

应用程序开发人员

测试错误处理。

  1. 如果它尚未运行,请输入以下命令,以启动 Shell 应用程序:

    npm start
  2. 在 Web 浏览器中,访问 http://localhost:4200/mfe1

  3. 验证错误页面是否已渲染。您应该会看到以下文本:

    Sorry, this page is not available.
应用程序开发人员
任务描述所需技能

部署微前端。

  1. 在 Amplify CLI 中,导航到微前端应用程序的根文件夹。

  2. 输入以下命令,以初始化 Amplify:

    amplify init
  3. 当提示您输入 Amplify 项目的名称时,请按 Enter 键。这样一来,就能重复使用 package.json 文件中的名称。

  4. 当提示您使用上述配置初始化项目时,请输入 Yes

  5. 当提示您选择身份验证方法时,请选择 AWS Profile

  6. 选择要使用的配置文件。

  7. 等待 Amplify 初始化项目。此过程完成后,您将在终端中收到一条确认消息。

  8. 输入以下命令,以将 Amplify 托管类别添加到微前端:

    amplify add hosting
  9. 当提示您选择插件模块时,请选择 Hosting with Amplify Console

  10. 当提示您选择类型时,请选择 Manual deployment

  11. 输入以下命令,以安装项目 npm 依赖项:

    npm install
  12. 输入以下命令,以将应用程序发布到 Amplify 控制台:

    amplify publish -y

    发布完成后,Amplify 会返回微前端的 URL。

  13. 复制 URL。更新 Shell 应用程序时,您需要用到此值。

应用程序开发人员、AWS DevOps

部署 Shell 应用程序。

  1. src/app/environments 文件夹中,打开 environments.prod.ts 文件。

  2. mfe1URL 值替换为已部署的微前端的 URL:

    export const environment = { production: true, mfe1URL: 'https://<env>.<Amplify-app-ID>.amplifyapp.com' };
  3. 保存并关闭 environments.prod.ts 文件。

  4. 在 Amplify CLI 中,导航到 Shell 应用程序的根文件夹。

  5. 输入以下命令,以初始化 Amplify:

    amplify init
  6. 当提示您输入 Amplify 项目的名称时,请按 Enter 键。这样一来,就能重复使用 package.json 文件中的名称。

  7. 当提示您使用上述配置初始化项目时,请输入 Yes

  8. 当提示您选择身份验证方法时,请选择 AWS Profile

  9. 选择要使用的配置文件。

  10. 等待 Amplify 初始化项目。此过程完成后,您将在终端中收到一条确认消息。

  11. 将 Amplify 托管类别添加到 Shell 应用程序中:

    amplify add hosting
  12. 当提示您选择插件模块时,请选择 Hosting with Amplify Console

  13. 当提示您选择类型时,请选择 Manual deployment

  14. 输入以下命令,以安装项目 npm 依赖项:

    npm install
  15. 输入以下命令,以将 Shell 应用程序发布到 Amplify 控制台:

    amplify publish -y

    发布完成后,Amplify 会返回已部署的 Shell 应用程序的 URL。

  16. 记下 Shell 应用程序的 URL。

应用程序开发人员、应用程序所有者

启用 CORS。

由于 Shell 和微前端应用程序独立托管在不同的域上,因此您必须在微前端启用跨源资源共享(CORS)。这允许 Shell 应用程序加载来自不同源的内容。要启用 CORS,请添加自定义标头。

  1. 在 Amplify CLI 中,导航到微前端的根文件夹。

  2. 输入以下命令:

    amplify configure hosting
  3. 当提示您配置自定义设置时,请输入 Y

  4. 登录 AWS 管理控制台,然后打开 Amplify 控制台

  5. 选择微前端。

  6. 在导航窗格中,选择托管,然后选择自定义标头

  7. 选择编辑

  8. 编辑自定义标头窗口中,输入以下内容:

    customHeaders: - pattern: '*.js' headers: - key: Access-Control-Allow-Origin value: '*' - key: Access-Control-Allow-Methods value: 'GET, OPTIONS' - key: Access-Control-Allow-Headers value: '*'
  9. 选择保存

  10. 重新部署微前端以应用新的自定义标头。

应用程序开发人员、AWS DevOps

在 Shell 应用程序上创建重写规则。

Angular shell 应用程序已配置为使用 HTML5 路由。如果用户执行硬刷新,Amplify 会尝试从当前 URL 加载页面。这便会生成 403 错误。为避免这种情况,您可以在 Amplify 控制台中添加一条重写规则。

要创建重写规则,请执行以下步骤:

  1. 在 Amplify CLI 中,导航到 Shell 应用程序的根文件夹。

  2. 输入以下命令:

    amplify configure hosting
  3. 当提示您配置自定义设置时,请输入 Y

  4. 打开 Amplify 控制台

  5. 选择 Shell 应用程序。

  6. 在导航窗格中,依次选择托管重写和重定向

  7. 重写和重定向页面上选择管理重定向

  8. 选择打开文本编辑器

  9. 在 JSON 编辑器中,输入以下重新导向:

    [ { "source": "/<*>", "target": "/index.html", "status": "404-200", "condition": null } ]
  10. 选择保存

应用程序开发人员、AWS DevOps

测试 Web 门户。

  1. 在 Web 浏览器中,输入已部署的 shell 应用程序的 URL。

  2. 验证 Shell 应用程序和微前端是否已正确加载。

应用程序开发人员
任务描述所需技能

删除应用程序。

如果您不再需要 Shell 和微前端应用程序,请将其删除。这有助于防止对您未使用的资源产生费用。

  1. 登录 AWS 管理控制台,然后打开 Amplify 控制台

  2. 选择微前端。

  3. 在导航窗格中,选择应用程序设置,然后选择常规设置

  4. 选择删除应用程序

  5. 在确认窗口中,输入 delete,然后选择删除应用程序

  6. 重复这些步骤,以删除 Shell 应用程序。

常规 AWS

故障排除

问题解决方案

运行 amplify init 命令时没有可用的 AWS 配置文件

如果您尚未配置 AWS 配置文件,您仍然可以继续执行 amplify init 命令。但是,当提示您选择身份验证方法时,您需要选择 AWS access keys 选项。准备好您的 AWS 访问密钥和私有密钥。

或者,您也可以为 AWS CLI 配置命名配置文件。有关说明,请参阅 AWS CLI 文档中的配置和凭证文件设置

加载远程条目时出错

如果在 Shell 应用程序的 main.ts 文件中加载远程条目时遇到错误,请确认已正确设置 environment.mfe1URL 变量。此变量的值应为微前端的 URL。

访问微前端时出现 404 错误

如果您在尝试访问本地微前端(例如 http://localhost:4200/mfe1)时出现 404 错误,请检查以下内容:

  • 对于 Shell 应用程序,请确认已正确设置 app-routing.module.ts 文件中的路由配置,并确认 loadRemoteModule 函数正确调用了微前端

  • 对于微前端,请验证 webpack.config.js 文件的 exposes 配置是否正确,并确认已正确生成 remoteEntry.js 文件。

其他信息

AWS 文档

其他参考资料