本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
使用 AWS Amplify、Angular 和模块联合为微前端创建门户
由 Milena Godau (AWS) 和 Pedro Garcia () 创作 AWS
代码存储库:Angular 微前端门户 | 环境:PoC 或试点 | 技术:Web 和移动应用程序;基础设施;网络;现代化 |
工作负载:开源 | AWS服务:AWSAmplify;AWSCLI |
Summary
微前端架构使多个团队能够独立处理前端应用程序的不同部分。每个团队都可以在不干扰应用程序其他部分的情况下开发、构建和部署前端的片段。从最终用户的角度来看,它似乎是一个单一的、有凝聚力的应用程序。但是,他们正在与多个由不同团队发布的独立应用程序进行交互。
本文档介绍如何使用 Angular 前端框架和模块AWS Amplify联合来创建微前端架构。在这种模式中,微前端通过外壳(或父级)应用程序在客户端进行组合。shell 应用程序充当检索、显示和集成微前端的容器。shell 应用程序处理全局路由,它加载不同的微前端。@angular-architects/模块联合插件将模块联邦与 Angular 集成在一起。您可以通过使用部署 shell 应用程序和微前端。 AWS Amplify最终用户通过基于 Web 的门户访问应用程序。
传送门是垂直分割的。这意味着微前端是整个视图或视图组,而不是同一视图的一部分。因此,shell 应用程序一次只能加载一个微前端。
微前端是作为远程模块实现的。shell 应用程序会延迟加载这些远程模块,这会将微前端初始化推迟到需要时再进行初始化。这种方法通过仅加载必要的模块来优化应用程序性能。这缩短了初始加载时间并改善了整体用户体验。此外,您可以通过 webpack 配置文件 (webpack.config.js) 在模块之间共享常见的依赖关系。这种做法促进了代码的重用,减少了重复,并简化了捆绑过程。
先决条件和限制
先决条件
产品版本
限制
微前端架构是构建可扩展且具有弹性的 Web 应用程序的强大方法。但是,在采用这种方法之前,了解以下潜在挑战至关重要:
集成 — 与整体式前端相比,关键挑战之一是复杂性可能会增加。编排多个微前端、处理它们之间的通信以及管理共享依赖关系可能更加复杂。此外,微前端之间的通信可能会带来性能开销。这种通信会增加延迟并降低性能。这需要通过有效的消息传递机制和数据共享策略来解决。
代码重复 — 由于每个微前端都是独立开发的,因此存在为通用功能或共享库复制代码的风险。这可能会增加应用程序的总体规模并带来维护难题。
协调和管理 — 跨多个微前端协调开发和部署流程可能具有挑战性。在分布式架构中,确保版本控制一致、管理依赖关系和维护组件之间的兼容性变得更加重要。建立明确的治理、指导方针以及自动测试和部署管道对于实现无缝协作和交付至关重要。
测试 — 测试微前端架构可能比测试单片前端更为复杂。它需要付出额外的努力和专门的测试策略来执行跨组件集成测试和 end-to-end测试,并验证跨多个微前端的一致用户体验。
在承诺使用微前端方法之前,我们建议您先查看 “了解和实现微前端”。 AWS
架构
在微前端架构中,每个团队都独立开发和部署功能。下图显示了多个 DevOps 团队如何协同工作。门户网站团队开发 shell 应用程序。shell 应用程序充当容器。它检索、显示和集成其他团队发布的微前端应用程序。 DevOps 您用于发布 AWS Amplify shell 应用程序和微前端应用程序。
架构图显示了以下工作流程:
门户网站团队开发和维护 shell 应用程序。shell 应用程序协调微前端的集成和渲染,以构成整个门户。
A 和 B 团队开发并维护一个或多个集成到门户中的微前端或功能。每个团队都可以在各自的微前端上独立工作。
最终用户使用 Amazon Cognito 进行身份验证。
最终用户访问门户,并加载 shell 应用程序。当用户导航时,shell 应用程序处理路由并检索请求的微前端,加载其捆绑包。
AWS 服务
其他工具
代码存储库
此模式的代码可在微前端门户中使用 Angular 和 Module Federation 存储库获得。 GitHub 此存储库包含以下两个文件夹:
最佳实践
微前端架构具有许多优点,但也会带来复杂性。以下是实现流畅开发、高质量代码和卓越用户体验的一些最佳实践:
规划和沟通 — 为了简化协作,请在前期规划、设计和清晰的沟通渠道上进行投资。
设计一致性 — 使用设计系统、样式指南和组件库,在微前端强制实现一致的视觉风格。这提供了有凝聚力的用户体验并加快了开发速度。
依赖关系管理 — 由于微前端是独立发展的,因此采用标准化的合同和版本控制策略来有效地管理依赖关系并防止出现兼容性问题。
微前端架构 — 为了实现独立的开发和部署,每个微前端都应该对封装的功能负有明确而明确的责任。
集成和通信 — 为了促进平稳集成并最大限度地减少冲突,请在微前端(包括APIs事件和共享数据模型)之间定义明确的合同和通信协议。
测试和质量保证 — 为微前端实施测试自动化和持续集成管道。这可以提高整体质量,减少手动测试工作量,并在微前端交互之间验证功能。
性能优化- 持续监控性能指标并跟踪微前端之间的依赖关系。这可以帮助您识别瓶颈并保持最佳的应用程序性能。为此,请使用性能监控和依赖关系分析工具。
开发者体验 — 通过提供清晰的文档、工具和示例,专注于开发者体验。这可以帮助您简化开发流程并加入新的团队成员。
操作说明
任务 | 描述 | 所需技能 |
---|
创建 shell 应用程序。 | 在 Angular 中CLI,输入以下命令: ng new shell --routing
输入以下命令以导航到项目文件夹: cd shell
注意:shell 和微前端应用程序的文件夹和项目结构可以完全独立。它们可以作为独立的 Angular 应用程序来处理。
| 应用程序开发人员 |
安装 插件。 | 在 Angular 中CLI,输入以下命令安装 @angular-architects/module-Federations 插件: ng add @angular-architects/module-federation --project shell --port 4200
| 应用程序开发人员 |
将微前端添加URL为环境变量。 | 打开环境.ts 文件。 mfe1URL: 'http://localhost:5000' 添加到environment 对象:
export const environment = {
production: false,
mfe1URL: 'http://localhost:5000',
};
保存并关闭环境.ts 文件。
| 应用程序开发人员 |
定义路由。 | 打开 app-routin g.module.ts 文件。 在 Angular 中CLI,输入以下命令从 @angular-architects/module-Federations 插件中导入loadRemoteModule 模块: import { loadRemoteModule } from '@angular-architects/module-federation';
按以下方式设置默认路由: {
path: '',
pathMatch: 'full',
redirectTo: 'mfe1'
},
为微前端设置路由: {
path: 'mfe1',
loadChildren: () => loadRemoteModule({
type: 'module',
remoteEntry: `${environment.mfe1URL}/remoteEntry.js`,
exposedModule: './Module'
})
.then(m => m.Mfe1Module)
},
保存并关闭 app-routin g.module.ts 文件。
| 应用程序开发人员 |
声明mfe1 模块。 | 在该src 文件夹中,创建一个名为 d ecl.d.ts 的新文件。 打开 d ecl.d.ts 文件。 将以下内容添加到文件中: declare module 'mfe1/Module';
保存并关闭 d ecl.d.ts 文件。
| 应用程序开发人员 |
为微前端做好预加载准备。 | 预加载微前端有助于 webpack 正确协商共享库和软件包。 打开主.ts 文件。 将内容替换为以下内容: 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));
保存并关闭主.ts 文件。
| 应用程序开发人员 |
调整HTML内容。 | 打开 app.component.html 文件。 将内容替换为以下内容: <h1>Shell application is running!</h1>
<router-outlet></router-outlet>
保存并关闭 app.component.html 文件。
| 应用程序开发人员 |
任务 | 描述 | 所需技能 |
---|
创建微前端。 | 在 Angular 中CLI,输入以下命令: ng new mfe1 --routing
输入以下命令以导航到项目文件夹: 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
| 应用程序开发人员 |
设置默认路由路径。 | 打开 mfe-routing.module.ts 文件。 按以下方式设置默认路由: {
path: '',
component: Mfe1Component
},
保存并关闭 mfe-routing.module.ts 文件。
| 应用程序开发人员 |
添加路mfe1 线。 | 打开 app-routin g.module.ts 文件。 按以下方式设置默认路由: {
path: '',
pathMatch: 'full',
redirectTo: 'mfe1'
},
添加以下mfe1 路线: {
path: 'mfe1',
loadChildren: () =>
import('./mfe1/mfe1.module').then((m) => m.Mfe1Module),
},
保存并关闭 app-routin g.module.ts 文件。
| 应用程序开发人员 |
编辑 webpack.config.js 文件。 | 打开 webpack.config.js 文件。 编辑该For remotes 部分以匹配以下内容: // For remotes (please adjust)
name: "mfe1",
filename: "remoteEntry.js",
exposes: {
'./Module': './src/app/mfe1/mfe1.module.ts',
},
在该shared 部分中,添加应用程序与 shell mfe1 应用程序共享的所有依赖关系: 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()
})
保存并关闭 webpack.config.js 文件。
| 应用程序开发人员 |
调整HTML内容。 | 打开 app.component.html 文件。 将内容替换为以下内容: <router-outlet></router-outlet>
保存并关闭 app.component.html 文件。
| 应用程序开发人员 |
任务 | 描述 | 所需技能 |
---|
运行mfe1 应用程序。 | 输入以下命令启动mfe1 应用程序: npm start
在 Web 浏览器中,访问http://localhost:5000 。 确认微前端可以独立运行。mfe1 应用程序应正确呈现,不会出现任何错误。
| 应用程序开发人员 |
运行 shell 应用程序。 | 输入以下命令启动 shell 应用程序: npm start
在 Web 浏览器中,访问http://localhost:4200/mfe1 。 验证mfe1 微前端是否嵌入在 shell 应用程序中。门户应用程序应正确呈现,不会出现任何错误,并且mfe1 应用程序应嵌入其中。
| 应用程序开发人员 |
任务 | 描述 | 所需技能 |
---|
创建模块和组件。 | 在 shell 应用程序的根文件夹中,输入以下命令为错误页面创建模块和组件: ng g module error-page --routing
ng g c error-page
| 应用程序开发人员 |
调整HTML内容。 | 打开 error-pag e.component.html 文件。 将内容替换为以下内容: <p>Sorry, this page is not available.</p>
保存并关闭 error-pag e.component.html 文件。
| 应用程序开发人员 |
设置默认路由路径。 | 打开 error-page-routing.module.ts 文件。 按以下方式设置默认路由: {
path: '',
component: ErrorPageComponent
},
保存并关闭 error-page-routing.module.ts 文件。
| 应用程序开发人员 |
创建加载微前端的函数。 | 打开 app-routin g.module.ts 文件。 创建以下函数: 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)
);
}
将mfe1 路径修改为以下内容: {
path: 'mfe1',
loadChildren: () => loadMFE(environment.mfe1URL)
},
保存并关闭 app-routin g.module.ts 文件。
| 应用程序开发人员 |
测试错误处理。 | 如果它尚未运行,请输入以下命令来启动 shell 应用程序: npm start
在 Web 浏览器中,访问http://localhost:4200/mfe1 。 验证错误页面是否已呈现。您应该会看到以下文本: Sorry, this page is not available.
| 应用程序开发人员 |
任务 | 描述 | 所需技能 |
---|
部署微前端。 | 在 Amplify 中CLI,导航到微前端应用程序的根文件夹。 输入以下命令来初始化 Amplify: amplify init
当系统提示你输入 Amplify 项目的名称时,请按 Enter。这会重复使用 p ackage.js on 文件中的名称。 当系统提示您使用上述配置初始化项目时,请输入Yes 。 当系统提示您选择身份验证方法时,选择AWS Profile 。 选择要使用的配置文件。 等待 Amplify 初始化项目。此过程完成后,您将在终端中收到一条确认消息。 输入以下命令将 Amplify 托管类别添加到微前端: amplify add hosting
当系统提示您选择插件模块时,选择Hosting with Amplify Console 。 当系统提示您选择类型时,选择Manual deployment 。 输入以下命令安装项目 npm 依赖项: npm install
输入以下命令,将应用程序发布到 Amplify 控制台: amplify publish -y
发布完成后,Amplify 会返回微前URL端的。 复制URL. 你需要这个值来更新 shell 应用程序。
| 应用程序开发者,AWS DevOps |
部署 shell 应用程序。 | 在 src/app/environments 文件夹中,打开 environmen ts.prod.ts 文件。 将该mfe1URL 值替换为已部署URL的微前端的值: export const environment = {
production: true,
mfe1URL: 'https://<env>.<Amplify-app-ID>.amplifyapp.com'
};
保存并关闭 envir onments.prod.ts 文件。 在 Amplify 中CLI,导航到外壳应用程序的根文件夹。 输入以下命令来初始化 Amplify: amplify init
当系统提示你输入 Amplify 项目的名称时,请按 Enter。这会重复使用 p ackage.js on 文件中的名称。 当系统提示您使用上述配置初始化项目时,请输入Yes 。 当系统提示您选择身份验证方法时,选择AWS Profile 。 选择要使用的配置文件。 等待 Amplify 初始化项目。此过程完成后,您将在终端中收到一条确认消息。 在外壳应用程序中添加 Amplify 托管类别: amplify add hosting
当系统提示您选择插件模块时,选择Hosting with Amplify Console 。 当系统提示您选择类型时,选择Manual deployment 。 输入以下命令安装项目 npm 依赖项: npm install
输入以下命令,将外壳应用程序发布到 Amplify 控制台: amplify publish -y
发布完成后,Amplify 会返回已部署URL的外壳应用程序的。 记下适用URL于 shell 应用程序的。
| 应用程序开发人员、应用程序所有者 |
启用CORS。 | 由于 shell 和微前端应用程序独立托管在不同的域上,因此您必须在微前端启用跨源资源共享 (CORS)。这允许 shell 应用程序从不同的来源加载内容。要启用CORS,您需要添加自定义标题。 在 Amplify 中CLI,导航到微前端的根文件夹。 输入以下 命令: amplify configure hosting
当系统提示您配置自定义设置时,请输入Y 。 登录 AWS Management Console,然后打开 Amplify 控制台。 选择微前端。 在导航窗格中,选择托管,然后选择自定义标题。 选择编辑。 在编辑自定义标题窗口中,输入以下内容: customHeaders:
- pattern: '*.js'
headers:
- key: Access-Control-Allow-Origin
value: '*'
- key: Access-Control-Allow-Methods
value: 'GET, OPTIONS'
- key: Access-Control-Allow-Headers
value: '*'
选择保存。 重新部署微前端以应用新的自定义标头。
| 应用程序开发者,AWS DevOps |
在 shell 应用程序上创建重写规则。 | Angular 外壳应用程序配置为使用HTML5路由。如果用户执行硬刷新,Amplify 会尝试从当前页面加载页面。URL这会生成 403 错误。为避免这种情况,您可以在 Amplify 控制台中添加一条重写规则。 要创建重写规则,请执行以下步骤: 在 Amplify 中CLI,导航到外壳应用程序的根文件夹。 输入以下 命令: amplify configure hosting
当系统提示您配置自定义设置时,请输入Y 。 打开 Amplify 控制台。 选择外壳应用程序。 在导航窗格中,选择托管,然后选择重写和重定向。 在 “重写和重定向” 页面上,选择 “管理重定向”。 选择 “打开文本编辑器”。 在JSON编辑器中,输入以下重定向: [
{
"source": "/<*>",
"target": "/index.html",
"status": "404-200",
"condition": null
}
]
选择保存。
| 应用程序开发者,AWS DevOps |
测试门户网站。 | 在 Web 浏览器中,输入已部署URL的 shell 应用程序的。 验证 shell 应用程序和微前端是否正确加载。
| 应用程序开发人员 |
任务 | 描述 | 所需技能 |
---|
删除应用程序。 | 如果您不再需要 shell 和微前端应用程序,请将其删除。这有助于防止对您未使用的资源收费。 登录 AWS Management Console,然后打开 Amplify 控制台。 选择微前端。 在导航窗格中,选择应用程序设置,然后选择常规设置。 选择 “删除应用程序”。 在确认窗口中,输入delete ,然后选择删除应用程序。 重复这些步骤以删除 shell 应用程序。
| 将军 AWS |
故障排除
问题 | 解决方案 |
---|
运行amplify init 命令时没有可用的 AWS 配置文件 | 如果您没有配置 AWS 配置文件,您仍然可以继续执行该amplify init 命令。但是,当系统提示您输入身份验证方法时,您需要选择该AWS access keys 选项。准备好您的 AWS 访问密钥和密钥。 或者,您可以为配置命名的配置文件 AWS CLI。有关说明,请参阅 AWS CLI 文档中的配置和凭据文件设置。 |
加载远程条目时出错 | 如果在 shell 应用程序的 main.ts 文件中加载远程条目时遇到错误,请确保该environment.mfe1URL 变量设置正确。此变量的值应为微前端URL的值。 |
访问微前端时出现 404 错误 | 如果您在尝试访问本地微前端(例如 at)时出现 404 错误http://localhost:4200/mfe1 ,请检查以下内容: |
其他信息
AWS 文档
其他参考资料