微前端为管理大型应用程序提供了一种可扩展的解决方案,通过将它们分割成更小、更独立的部件。这种方法允许专门的团队分别开发、测试和部署应用程序的各个部分,提高了效率并减少了复杂性。
微前端将微服务原则应用于前端开发,将大型应用程序分解成可管理的部分。这些部件,或称为微应用,可以独立开发并通过路由集成。有关微前端的更深入信息,特别是涉及到模块联邦的部分,我们建议阅读我们的模块联邦文章。
用户看到一个统一的应用,而开发者则在部署和服务选项中享有灵活性,包括用于集成微服务的模块联邦。
微前端允许使用不同的框架或库来构建应用程序的不同部分,提供了灵活性但也带来了挑战,如团队流动性。像单页面SPA或特定框架的解决方案,如Angular的Nx,帮助将这些技术集成到一个连贯的应用中。目标是独立构建、测试和部署每个微应用,同时确保用户无缝体验。
大型应用程序可能会因为测试和构建耗时而遭受重负,以及本地服务速度缓慢。通过将应用程序分割成更小的部分转变为微前端,可以显著缓解这些问题。
实施微前端有许多方法,有各种指导和资源可用。一些专注于从头构建微前端,这对于预期要大规模扩展的新项目来说是理想的。
然而,本指南集中在重构现有应用程序,可能使用Angular CLI构建,将其分割成共享库和单个应用。然后这些组件在不破坏统一用户体验的同时,增强开发效率,无缝集成在更大的应用程序中。
对于我们对微前端的探索,我们将使用一个示例应用程序。该应用程序虽然不大也不复杂,但包含几个服务,演示了它们如何可以与微前端架构中的每个微应用集成。
应用程序的结构反映了使用Angular CLI创建新项目时通常会得到的样子。主要元素包括:
auth
)和用户管理(users
)。目录结构如下:
目标是将服务和模型重构为可以跨微应用共享的库。另一方面,功能模块将被转换为各自的应用程序。这种方法确保了模块化,并便于每个功能的独立开发和部署。
应用程序中当前的路由设置使用懒加载,提高了性能和用户体验。下面是展示路由策略的一个摘录:
This routing module demonstrates the use of guards (isLogged
and isNotLogged
) to manage access to different routes based on user authentication status, and dynamic imports for lazy loading of feature modules.
Migrating a complex application to a micro-frontend architecture can be challenging. To facilitate this process, clear steps and possibly additional tooling (for better dependency management) are essential.
Identify Independent Files: Start by pinpointing files that do not have dependencies but are used across services and feature modules. For example, in our sample application, this applies to the models
folder, which contains models used throughout the application but doesn't depend on any other files.
Create a New Library for these Files: Use Angular CLI to generate a library that will house these independent files. The command for this is:
这个命令会产生以下动作:
projects
文件夹,包含 models
库。ng-packagr
作为依赖。angular.json
和 tsconfig.json
以包含新的库。tsconfig.json
中的路径映射以避免与npm模块发生潜在的冲突。建议的前缀是 @@
,因为npm模块名称不能包含双感叹号。package.json
中的名称适合注册表。否则,你可以选择一个方便的名称。models
文件夹的内容转移到新库中。生成的库将包含默认的组件、模块和服务,这些可以被移除。将用户模型文件放置在库的 lib
文件夹中。public-api.ts
文件以从 lib
文件夹导出适当的内容。git mv
而不是操作系统功能来移动文件。这样可以确保Git更好地跟踪更改。models
库的文件夹结构应该组织得清晰易懂,便于访问。
更改导入路径:将现有的导入路径替换为新库的路径。例如,更改:
确保路径与 tsconfig.json
文件中指定的相匹配。
解决错误:最初,你可能会遇到由于库未构建而导致的错误。通过运行以下命令来解决这个问题:
这个命令会编译 models
库,使 TypeScript 能够正确引用 @@models
。
成功将独立代码迁移到库中后,下一步涉及到处理也可以隔离的依赖代码。继续以我们的示例为例,我们将专注于将 auth
服务及其守卫迁移到一个独立的库中。这个过程与为 models
库采取的步骤相似。
使用 Angular CLI 创建 auth
库,命令如下:
从 lib
文件夹中移除默认内容,并将 auth
文件夹中的所有内容转移到其中。更新 public-api.ts
文件以反映这些更改。
public-api.ts
文件应该类似于如下结构:
使用Angular CLI编译auth
库:
将应用程序的导入语句更改为使用新的 auth
库。
值得庆祝!你的应用程序的部分已经成功迁移到库中。这不仅保持了应用程序的运行,还有可能加快了速度,因为Angular不需要重建整个应用程序。你现在拥有了几个具有独立测试和构建功能的库,适用于更大应用程序中的组件、服务、管道和其他元素的共享。
对于更复杂的应用程序,请考虑使用ng-packagr的次要入口点(Secondary Entrypoints)功能将常用的项(例如组件或服务)进行分组。这需要进行额外的配置调整。
已经学会了如何打包库,我们现在转向将一个特性模块迁移到它自己的应用程序。
在我们的示例中,选择 Login
特性模块进行迁移。确保此模块使用的共享工件已经在它们各自的库中。像 users
服务这样的其他服务可以稍后迁移。
使用Angular CLI创建 login
应用程序:
--routing标志对于应用内的导航至关重要。
使用以下命令测试新创建的应用程序:
如果主应用程序正在运行,你可能需要使用不同的端口。
转移特性模块:不要像处理库那样替换文件,而是在新应用程序的 src
中创建一个 feature
文件夹,并将 login
文件夹移入其中。
更新路由:修改 login
应用程序的 app-routing.module.ts
,以便在根路由上提供 Login
模块。
调整 AppComponent:确保 login
应用的 app.component.html
包含一个 <router-outlet></router-outlet>
标签,以便路由能够正确工作。
最初,新应用程序可能看起来没有样式。从主应用程序中复制 styles.scss
文件到新应用程序中以解决这个问题。未来的文章将深入探讨跨应用程序共享样式。
如果操作正确,login
应用程序现在应该可以独立运行,有样式且功能完备,这标志着你朝着完全实现微前端架构迈出的重要一步。
在将 Login
应用程序设置为独立实体后,下一步关键步骤是将其与主应用程序集成。这涉及构建 Login
应用为库,并使用主模块中现有的懒加载特性进行导入。
angular.json
修改项目配置:在 angular.json
中,复制一个库配置,将其放在 login
配置下以更好地组织。将键重命名为 login-lib
并更新引用(如 root
、sourceRoot
)以指向 login
应用程序。
login
应用程序的特定路径和设置。创建 ng-package.json
:此文件对于指导 ng-packagr
如何打包应用程序至关重要。从另一个库中复制一个现有的 ng-package.json
文件,将其粘贴到 Login
应用程序的根文件夹中。将 dest
键更新为 "../../dist/login-lib"
以指明构建输出目录。
public-api.ts
:这个文件不同于典型的库设置,应该在 src
文件夹下创建。它应该只导出 Login
特征模块:准备 package.json
:从另一个库复制一个 package.json
到 Login
应用的根目录,并确保更新项目名称。
构建命令:执行 Angular CLI 构建命令:
这个过程会编译 Login 模块为库。
更新 tsconfig.json:在 tsconfig.json 中为 login-lib 添加一个新的路径映射,指向 "dist/login-lib"。这一步对 TypeScript 正确定位库至关重要。
修改应用程序路由:在 app-routing.module.ts 中,更新懒加载路径以使用新库:
将这些更改应用之后,你可以像往常一样启动应用程序。现在作为一个单独项目的 Login
模块应该能够在主应用程序中无缝地工作。
自动化构建:为了简化流程,考虑使用像 Lerna 这样的工具进行自动化构建和依赖项管理。这在处理多个库和应用程序时尤其有帮助。
版本管理:当前的设置没有使用库的版本控制,这可能会使得引入破坏性更改变得复杂。实施版本控制策略对长期维护来说可能是有益的。