写点什么

基于 Angular 的微前端理念与实践

  • 2022-10-31
    北京
  • 本文字数:4569 字

    阅读完需:约 15 分钟

基于Angular的微前端理念与实践

现代Web应用正在变得越来越庞大和复杂,有时候这样的应用会由不同的团队来管理。应用可能会包含不同团队开发的特性,在交付整个应用之前,我们可能希望只将某些特定的功能发布到生产环境中。如果整个应用只有一个仓库(repo),那我们该如何管理不同的团队和不同的发布周期呢?

 

这些复杂的应用大多位于客户端,使其更加难以维护。这种单体式的臃肿应用还有一些其他的问题。在本文中,我将会讨论微前端的优势、劣势、实现方式以及其他的内容。

简介

 

微前端是一些小型的应用,大多会根据子域或功能进行划分,它们互相协作来交付一个更大的应用。在深入介绍微前端的实现之前,我们将会阐述什么是微前端以及为什么要使用它。

 

通常,项目都有不同的规模和不同的需求。如果你的项目非常简单,只有两三个页面,那么根本没有必要考虑微前端。你可以直接使用自己选择的任意框架来实现,比如Angular、React 或 Vuejs。

 

但是,事实并非总是如此。有时候,你的前端应用是另一个大型应用的一小部分,或者你的应用有很多的区域和特性组成,它们由不同的团队进行开发,又或者你的应用要按特性依次发布到生产环境中。如果你正在面临这样的场景,那么就需要考虑一下微前端了。我们看一下这张图片。



如上图所示,我们有 6 个前端应用互相协作来交付一个更大的应用。这些应用之间的通信可以借助事件总线、window 对象或发布/订阅方法来实现。每个应用都可以由不同的团队和任意框架实现。每个应用都可以独立地与其后端或端点进行交互。这里有一个 bootstrap/launch 应用,它会负责加载所有其他的应用,并根据用户的交互或路由在 DOM 中挂载或卸载它们。

 

这种微前端架构主要有如下的优势。

 

  • 应用会很小:显然,当大的应用按照区域、页面或特性进行拆分后,每个应用都会变得很小。

  • 应用是独立的:由于所有的应用都是单独拆分和开发的,所以它们是相互独立的。

  • 应用更易于理解:因为每个应用更小,由单一团队进行开发,所以更易于理解。

  • 应用更易于开发和部署:由于这些应用本身都很小,都由单一的团队进行开发,所以很易于开发和部署。我们甚至可以独立部署它们。

  • 应用更易于测试:我们必须为大型的应用编写成千上万的单元测试,并且需要一直运行。这会拖慢我们的部署过程。在实现微前端之后,每个应用都有数量更少的单元测试,并且可以独立运行自己的单元测试。

  • 应用的开发会更迅速:因为应用都有独立的团队,所以整个开发会更迅速、更容易。

  • CI/CD 会更简单:每个应用都可以单独集成和部署,这使得 CI/CD 过程会变得更加容易。当我们修复某个应用或者引入新的特性时,不用考虑整个应用的情况,因为所有的特性都是独立的。

  • 独立的技术栈和版本:我们可以为每个应用选择自己的技术栈,只不过这种情况不太多见。但是,我们可以使用相同技术栈的不同版本。例如,有些团队可能有足够的灵活性和时间来引入和测试同一技术栈的较新版本。

  • 没有共享的代码:在大型的应用中,我们倾向于跨特性共享代码,但是,这并不能很好地进行扩展,而且随着应用越来越大,会引入很多缺陷和相互依赖。微前端中则没有这样的问题,因为我们不会共享代码,除非它是一个哑(dumb)组件。

  • 能够很容易地在不影响旧有架构的情况下变更架构:有时候,我们必须要扩展旧的架构,但是可能没有足够的开发人员来实现或扩展架构。借助微前端的方式,我们可以使用最新的技术栈开发新特性,并独立进行交付。

微前端的特点

 

  • 每个前端应用代表整个应用的一个特定功能或子域。

  • 每个前端应用都可以由一个独立的团队来实现。

  • 每个前端应用可以采用不同的技术来实现。

  • 它们之间不能共享逻辑,而且相互独立。

  • 每个前端应用都由一个团队来负责。

如何拆分应用

 

我们看一下如何将大型应用拆分为微前端。在这方面,没有拆分应用的具体标准,我们可以根据自己的需要以多种方式进行拆分。我们会看到各种拆分应用的方式。

按照特性

 

这是最常见的方法,因为我们可以很容易地划分应用的功能。例如,如果应用有三个特性,分别是 Dashboard、Profile 和 Views,我们可以将每个特性作为一个单独的应用,并在 Launch.js 的辅助下在 DOM 中挂载和卸载它们。这个 Launch.js 可以是一个独立的应用,也可以只是一个简单的 JavaScript 应用。


按照区域

 

在有些应用中,每个区域都有很多功能,例如,在 coinbase、Gmail 中。在这种情况下,我们可以将每个区域作为一个新的应用来实现。


按页面

 

有些应用的功能是按页面划分的。每个页面都有一些独立的功能。我们可以通过页面来划分应用。在下图中,我们有四个页面,可以分别创建四个应用。

 

按照域

 

基于域来拆分应用也是最常见的方式之一。


微前端的不同实现方式

 

我们有很多实现微前端的方式,我发现最常用的是如下 6 种:

 

  • Iframes

  • 借助 NGINX

  • Web Component/Angular 元素

  • Angular 库

  • Monorepos

  • 定制化的编排器

微前端框架

 

微前端出现至少已经有两年了,但它依然是一个新兴领域。你可能会问有没有相关的框架或库帮助我们实现这种架构,从而减轻我们工作。答案是肯定的,目前已经有一些相关的库或框架了。


single-spa

 

single-spa 是一个用于前端微服务的 JavaScript 框架,可以用最流行的三个框架/库来实现,即 Angular、React 和 Vue.js。它可以根据需要懒加载应用,请查阅他们的网站以了解更多信息。

frint.js

 

frint.js 是一个模块化的 JavaScript 框架,用于构建可扩展和反应式的应用。目前,它不支持 Angular,但支持 React。如果你要从头开始构建一个反应式应用,而且刚刚开始的话,这个框架会特别适合你。请参阅他们的网站以了解更多信息。

使用 Angular 的微前端项目实例

 

有了这些基础知识之后,我们在single-spa框架的协助下构建一个 Angular 项目的样例,我希望构建一个简单的应用以便于演示。

 

我们将按下图所示,把这个应用分成多个组成部分。我们一共要实现 4 个应用,分别是 HeaderApp、DashboardApp、FooterApp 和根应用。

 


如下是四个应用的代码仓库,你可以在自己的机器上分别克隆并运行它们。

 

// root app runs on port 4200git clone https://github.com/ahmedbhl/micro-root.gitnpm installnpm start// micro header runs on port 4300git clone https://github.com/ahmedbhl/micro-header.gitnpm installnpm start// micro dashboard runs on port 4202git clone https://github.com/ahmedbhl/micro-dashboard.gitnpm installnpm start// micro footer runs on port 4201git clone https://github.com/ahmedbhl/micro-footer.gitnpm installnpm start
复制代码

 

然后,可以在 http://localhost:4200/ 上访问整个应用程序

 


如下是根应用的 index HTML 文件。我们在第 10 行导入了这三个应用,并以适当的名称和位置注册了这些应用。由于我们在页面加载时加载了所有的应用程序,所以没有定义任何特定的上下文路径。

 

<!DOCTYPE html><html>  <head>    <meta http-equiv="Content-Security-Policy" content="default-src *  data: blob: 'unsafe-inline' 'unsafe-eval'; script-src * 'unsafe-inline' 'unsafe-eval'; connect-src * 'unsafe-inline'; img-src * data: blob: 'unsafe-inline'; frame-src *; style-src * data: blob: 'unsafe-inline'; font-src * data: blob: 'unsafe-inline';">    <meta charset="utf-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <title>Your application</title>    <meta name="viewport" content="width=device-width, initial-scale=1">    <meta name="importmap-type" content="systemjs-importmap">    <script type="systemjs-importmap">      {        "imports": {          "footer": "http://localhost:4201/main.js",          "dashboard": "http://localhost:4202/main.js",          "header": "http://localhost:4300/main.js",          "single-spa": "https://cdnjs.cloudflare.com/ajax/libs/single-spa/4.3.5/system/single-spa.min.js"        }      }    </script>    <link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/single-spa/4.3.5/system/single-spa.min.js" as="script" crossorigin="anonymous" />    <script src='https://unpkg.com/core-js-bundle@3.1.4/minified.js'></script>    <script src="https://unpkg.com/zone.js"></script>    <script src="https://unpkg.com/import-map-overrides@1.6.0/dist/import-map-overrides.js"></script>    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/4.0.0/system.min.js"></script>    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/4.0.0/extras/amd.min.js"></script>    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/4.0.0/extras/named-exports.js"></script>    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/4.0.0/extras/named-register.min.js"></script>    <style>    </style>  </head>  <body>    <script>      System.import('single-spa').then(function (singleSpa) {        singleSpa.registerApplication(          'header',          function () {            return System.import('header');          },          function (location) {            return true;          }        )        singleSpa.registerApplication(          'dashboard',          function () {            return System.import('dashboard');          },          function (location) {            // return location.pathname.startsWith('/app2');            return true;          }        )        singleSpa.registerApplication(          'footer',          function () {            return System.import('footer');          },          function (location) {            // return location.pathname.startsWith('/app1');            return true;          }        );        singleSpa.start();      })    </script>    <import-map-overrides-full></import-map-overrides-full>  </body></html>
复制代码

 

我们可以设置“/header”的位置路径,这样当浏览器的 URL 导航到“/header”时就会加载 header。我们来测试一下。

 

<script>      System.import('single-spa').then(function (singleSpa) {        singleSpa.registerApplication(          'header',          function () {            return System.import('header');          },          function (location) {            return location.pathname.startsWith('/header');            // return true;          }        )
复制代码

 

总结

 

我知道微前端是一个很时尚的东西,但你不应该在每个应用中都使用它。如果你的应用程序很小,就没有必要这样做,不要把事情复杂化。这种方式的目的是让我们的整个过程更加顺畅,而不是增加复杂性。所以在使用该方式之前,先要进行必要的判断。


原文链接:

https://blog.devgenius.io/angular-micro-frontend-4dad619c4277


相关阅读:

微前端如何改变 Angular 的未来?

Angular 13 发布:全面弃用 View Engine

Angular、React 和 Vue 三大框架,Web 开发该如何选择?

2022-10-31 23:243904

评论

发布
暂无评论
发现更多内容

不愧是阿里内部Spring Boot笔记,从头到尾全是干货

小小怪下士

Java spring 程序员 阿里 springboot

FOTSL:端到端的文本检测与识别方法的原理方法与优势

合合技术团队

人工智能 场景 端口 文本检测 文本识别

Docker PHP 入门实践 (三)

Felix

php Docker thinkphp 11月月更

uniapp引入 iconfont

源字节1号

微信小程序 软件开发 前端开发 后端开发

量子编程实践:Bell Pair电路及Deutsch算法

启科量子开发者官方号

#python #量子计算 #人工智能 #AI框架

喜讯!麦聪DaaS平台荣获“2022行业信息化优秀产品”奖

雨果

数字化转型 DaaS数据即服务 麦聪软件

BI系统打包Docker镜像及部署的技术难度和实现

葡萄城技术团队

Docker 容器 BI

设计模式学习-基础知识

肥晨

设计模式 11月月更 设计模式基础

从演进的视角理解微服务架构

苏格拉格拉

架构 微服务 微服务架构 架构演进

深圳中心化区块链交易所开发安全的重要性

W13902449729

区块链交易所搭建

PingCAP 推出 TiDB Cloud Serverless Tier BETA 版

PingCAP

TiDB

Docker PHP 入门实践(一)

Felix

php 实战案例 Docker 镜像 11月月更

智采云火了的背后,是企业降本增效的刚需

ToB行业头条

Dubbo核心技术

苏格拉格拉

分布式 微服务 dubbo RPC 集群

马蜂窝毕博:分析完这9点工作原理,我们最终选择了 Apache SeaTunnel!

Apache SeaTunnel

开源 技术选型 数据集成 Seatunnel 数据集成平台

LED显示屏有色差要怎么处理?

Dylan

LED显示屏 全彩LED显示屏 led显示屏厂家

Docker PHP 入门实践(二)

Felix

php Docker 实战 11月月更

Redis数据结构

苏格拉格拉

redis 缓存 Redis 数据结构

集群并发下的数据覆盖问题

苏格拉格拉

缓存 分布式 并发 一致性

大咖说·我和我的伙伴们|云原生携手禾连健康助力医疗行业发展

大咖说

阿里云 微服务 云原生

python数据分析-开篇什么是数据分析

AIWeker

Python 人工智能 数据分析 11月月更

一文带你详细了解JVM运行时内存

程序员小毕

Java 程序员 面试 后端 JVM

QuTrunk与Paddle结合实践--VQA算法示例

启科量子开发者官方号

Python 人工智能 ai框架 量子计算 量子编程

Redis核心技术

苏格拉格拉

redis 架构 持久化 部署 集群

「百幄」之办公平台:进一道门,办所有事

融云 RongCloud

数字化 办公

Spring Boot「24」DAO 模式与 Repository 模式

Samson

Java spring Spring Boot 学习笔记 11月月更

并发编程中的锁、条件变量和信号量

C++后台开发

Go 并发编程 linux开发 C++开发

产品网站的FAQ页面该如何编辑?

Baklib

产品 FAQ

【10.28-11.04】写作社区优秀技术博文一览

InfoQ写作社区官方

优质创作周报

稳定性治理方法论

苏格拉格拉

方法论 稳定性

Baklib|如何搭建在线帮助中心站点?

Baklib

基于Angular的微前端理念与实践_大前端_Ahmed Bouhlel_InfoQ精选文章