HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

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

评论

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

【一Go到底】第二十二天---函数参数传递方式、变量作用域

指剑

Go golang 10月月更

Linux基础命令

渔戈

Linux ubuntu 10月月更

spring事务失效的情况

急需上岸的小谢

10月月更

在线问题反馈模块实战(十)​:实现图片预览功能

bug菌

springboot 项目开发 10月月更

嵌入式 Linux 入门(二、Linux 文件系统、文件类型及权限管理)

矜辰所致

Linux 文件系统 10月月更

在线问题反馈模块实战(十一)​:实现图片下载功能

bug菌

springboot 项目开发 10月月更

Linux系统-进程控制

可口也可樂

Linux 10月月更 Linux进程

前端布局之浅谈BFC

CoderBin

CSS 面试 前端 10月月更

可靠消息最终一致性分布式事务

C++后台开发

数据库 分布式 后端开发 linux开发 C++开发

学习线程池原理从手写一个线程池开始

JAVA旭阳

Java 线程池 10月月更

不错的项目管理系统厂商有哪些?

爱吃小舅的鱼

【LeetCode】下一个更大元素单调栈Java题解

Albert

算法 LeetCode 10月月更

ES6之let、const与var

木偶

JavaScript 前端 ES6 10月月更

Flex布局教程:语法篇

木偶

css3 前端 10月月更

Pycharm配置远程解释器并自动上传代码

渔戈

pycharm 开发工具 10月月更

“程”风破浪的开发者|一文GET钉钉连接平台

六月的雨在InfoQ

学习方法 钉钉宜搭 10月月更 “程”风破浪的开发者 钉钉连接平台

在线问题反馈模块实战(十二)​:实现图片删除功能

bug菌

springboot 项目开发 10月月更

深入浅出ES6中的解构

木偶

JavaScript 前端 ES6 10月月更

Linux 驱动开发:USB无线wifi驱动开发(MT7601)、完成WIFI管理工具安装

DS小龙哥

10月月更

Ubuntu 20.04上安装和配置MySql5.7

渔戈

ubuntu 开发工具 10月月更

Linux系统-进程概念

可口也可樂

Linux 10月月更 Linux进程

Linux系统-进程地址空间

可口也可樂

Linux 10月月更 Linux进程地址空间

双向带头循环链表的(增删查改)的实现

lovevivi

c 数据结构 10月月更

python爬虫--网络歌曲

木偶

Python 爬虫 10月月更

苏州太仓| 第六届“创赢太仓”全球创业大赛博士后专场项目征集公告

科兴未来News

生物医药 双创大赛承办 苏州 医疗器械 博士后

鸿蒙开发实例 | 分布式涂鸦

TiAmo

华为 华为云 云开发 10月月更

单链表的(增删查改)的实现

lovevivi

c 数据结构 10月月更

顺序表的(增删查改)实现

lovevivi

c 数据结构 10月月更

消息中间件:概念&应用

agnostic

消息中间件

规划兼职工作

掘金安东尼

算法 10月月更

开源软件与开源协议的法律问题分析

Andy

开源 架构 调研

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