写点什么

基于 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:243841

评论

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

从零开始学习3D可视化之2D界面

ThingJS数字孪生引擎

大前端 可视化 3D可视化 数字孪生

FIL云算力系统开发(案例)

開發15347427695

服务限流限流算法、限流策略以及该在哪里限流

Jokay

高可用 分布式限流 限流算法 限流 单机限流

【大牛疯狂教学】熬夜整理2021最新Android高级笔试题

欢喜学安卓

android 程序员 面试 移动开发

详解Spring中Bean的作用域与生命周期

华为云开发者联盟

spring 容器 ioc bean Bean对象

mysqldump备份技巧分享

Simon

MySQL 逻辑备份

解读 AppStore 新功能:自定义产品页面和 A/B Test 工具

37手游iOS技术运营团队

ios apple AB testing实战 appstore 马甲包

对标Shopify的千亿市值,有赞还要走多久?

ToB行业头条

SaaS 电商SaaS

ICML 2021顶会来袭,百度飞桨AI硬实力集中展现

百度大脑

人工智能 机器学习 百度

【CRUD工程师的末路?程序员开发福音?】AI编程工具——GitHub Copilot推介

恒生LIGHT云社区

人工智能 GitHub 编程

MDF智能合约挖矿系统开发(案例)

開發15347427695

物联网通信技术,那些你不知道的事

华为云开发者联盟

物联网 网络 通信 有线 无线

Triton推理服务器在阿里云机器学习PAI-EAS公测啦!!!

阿里云大数据AI技术

【大牛系列教学】2021年Android程序员职业规划

欢喜学安卓

android 程序员 面试 移动开发

星火矿池APP源码开发

获客I3O6O643Z97

区块链+

有图有真相!平衡二叉树AVL实现

Ayue、

数据结构

IPFS矿机最新消息?Ipfs矿机公司实力排行?

fil矿机 ipfs矿机 ipfs矿机最新消息是什么? ipfs矿机公司实力排名?

频繁创建基于Etcd实现的分布式锁会有什么问题?

BUG侦探

分布式锁 etcd 内存泄漏

我们为什么要选择 Rust 而不是 Golang 或 C/C++ 来开发 TiKV ?

恒生LIGHT云社区

编程 rust 语言 & 开发

程序员上班“划水”向阿里猛投简历,两次被刷后,终成“菜鸟”P6

Java 程序员 架构 计算机

策略+IOC 消灭ifelse,拿来吧你

skow

Java 设计模式 代码设计

Flutter Android 工程结构及应用层编译源码深入分析

工匠若水

flutter android dart Gradle 工匠若水

穿越六年艰难转型,明道云终于再获主流投资

明道云

互联网

如何优雅地关闭SpringBoot应用程序?听我给你讲

麦洛

Spring Boot

和12岁小同志搞创客开发:遥控舵机

不脱发的程序猿

DIY 创客开发 控制舵机

图解URL、URI和URN 区别

devpoint

API url 7月日更

权威认可!腾讯云数据安全中台入选2021先锋实践案例

腾讯安全云鼎实验室

#腾讯云 数据安全中台

《2021 年中国视频云场景应用洞察白皮书》联合首发!

阿里云视频云

阿里云 计算机视觉 音视频 直播架构 视频云

MARVEL奇迹币矿池系统软件开发

获客I3O6O643Z97

挖矿矿池系统开发案例 云算力软件系统开发定制 蚂蚁矿池

短视频商城系统开发(案例)

開發15347427695

九环智能合约系统开发(案例)

開發15347427695

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