转发:走进微前端架构的世界


前端开发在程序猿中无疑是一个比较苦逼的存在,作为一个前端开发,你必须要掌握Javascript,HTML,CSS这三大基础。Javascript作为网络时代最为重要的开发语言,由于其设计上的限制,一直在演进,经历了ES3,ES5,ES6(ECMAScript 2015)... ... 而简单的CSS也无法完成你复杂的需求,你需要Less/Sass/Sytlus来增强你的CSS的功能。这些还远远只是一小部分,你还需要了解:

  • 你需要有网络的基本知识,和常见的API接口例如HTTP/REST/GraphQL
  • 你需要知道浏览器的兼容性,什么IE,Chrome,Safari,Firefox,等等
  • 你需要知道应用如何打包,了解 Webpack ,还有gulp, Babel, Parcel, Browserify, and Grunt等是怎么工作的
  • 你需要熟悉HTML的DOM操作,和相关的工具库例如jquery和d3js
  • 需要了解不同的框架和他们的优缺点 例如React,AngularJS和VueJS,这三大框架都不兼容,而且各自都有自己庞大的生态
  • 虽然NodeJS主要用于后端开发,但是很多前端的工具链和这个相关,例如构建工具 npm,yarn ...
  • 如果你的项目足够复杂,你需要引入Monorepo,使用例如lerna,nx等工具来管理多个项目的包和依赖
  • 你需要掌握基本的前端测试工具和框架,例如:Jasmin,Jest,Selenium,Mocha等等

最可怕的是,这些东西都在飞快地发展和变化中,当你正忙于学习ES8,ES9,ES10的新特性的时候,今天我要和大家分享的希望不是压死前端开发小骆驼的最后一根稻草--微前端。

目录:

1.什么是微前端

2.为什么需要微前端,它有什么优势

3.如何实现微前端架构

4.运行时微前端的具体实现方式

5.微前端的问题和缺点

一、什么是微前端

而提到微前端就离不开微服务,大家对微服务都比较熟悉了,微服务允许后端体系结构通过松散耦合的代码库进行扩展,每个代码库负责自己的业务逻辑,并公开一个API,每个API均可独立部署,并且各自由不同的团队拥有和维护。

前端架构经历了从单体,到前后端分离,再到微服务,最终发展到现在的微前端的过程如下图所示:

微前端的思路是把微服务的架构引入到前端,其核心都是要能够以业务为单元构建端到端的垂直架构,使得单个的团队能够独立自主的进行相关的开发,同时又具备相当的灵活性,按需求来组成交付应用。

“微前端”一词最早于2016年底在ThoughtWorks 技术雷达中提出的。它将微服务的概念扩展到了前端世界。当前的趋势是构建一个功能强大且功能强大的浏览器应用程序(也称为单页应用程序),该应用程序位于微服务架构之上。随着时间的流逝,通常由一个单独的团队开发的前端层会不断增长,并且变得更加难以维护。

微前端背后的想法是将网站或Web应用程序视为由独立团队拥有的功能的组合。每个团队都有自己关心和专长的不同业务或任务领域。一个团队是跨职能的,并且从数据库到用户界面,端到端地开发其功能。

但是,这个想法并不新鲜。它与“单体系统”概念有很多共同点。在过去,类似的方法被称为“垂直系统的前端集成”。但是微前端显然是一个更友好,更轻巧的术语。

在微服务的架构中,后台的服务已经按照业务进行了分离,而前端仍然是一个单体构建,通过网关来调用不同的后台服务。这个微服务的思路是相违背的,这也就造成了你的后端团队是按照业务分割的,但是前端团队仍然是一个整体。微前端可以有效地改进这一点。

微前端的核心思路其实是远程应用程序,包含组件/模块/包的运行时加载

如上图,对于用户而言,访问的是一个微前端的容器(container),容器加载运行在远程服务上的应用,把这些远程应用作为组件/模块/包在本地浏览器中加载。

  • 组件是底层UI库的构建单元
  • 模块是相应运行时的构建单元
  • 包是依赖性解析器的构建单元
  • 微前端是所提出的应用程序的构建块

二、为什么需要微前端?

它有什么优势?

在前面我们看到的微前端之前的架构,所有的前端还是一个单体,前端团队会依赖所有的服务或者后台的API,前端开发会成为整个系统的瓶颈。使用微前端,就是要让前端业务从水平分层变为垂直应用的一部分,进入业务团队,剥离耦合。

那么微前端有什么好处,为什么要采用微前端架构呢?

  • 各个团队独立开发,相互不影响,独立开发、独立部署,微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
  • 增量升级,在面对各种复杂场景时,通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略。因为是运行时加载,可以在没有重建的情况下添加,删除或替换前端的各个部分。
  • 不受技术影响,每个团队都应该能够选择和升级其技术栈,而无需与其他团队进行协调。也就是说A应用可以用React,而B应用使用Vue,大家可以通过同一个微前端来加载
  • 独立运行时,每个微应用之间状态隔离,运行时状态不共享。隔离团队代码,即使所有团队都使用相同的框架,也不要共享运行时。构建自包含的独立应用程序。不要依赖共享状态或全局变量。
  • 建立团队命名空间,对于CSS,事件,本地存储和Cookies,可以避免冲突并阐明所有权。

因此,微前端和微服务的本质都是关于去耦合。而只有当应用程序达到一定规模时,这才开始变得更有意义。

三、如何实现微前端架构

微前端不是一个库,是一种前端架构的设计思路,要实现微前端,本质上就是在运行时远程加载应用。

实现微前端,有几个思路,从构建的角度来看有两种,编译时构建微前端和运行时构建微前端:

  • 编译时微前端,通常将第三方库中的组件作为包,在构建时引入依赖。这种实现引入新的微前端需要重新编译,不够灵活。编译时的微前端可以通过Web Components,Monorepo等方式来实现。其中Monorepo非常流行,常见的工具有nx,rush,lerna等。
  • 运行时微前端,是一次加载或通过延迟加载按需动态将微型前端注入到容器应用程序中时。当引入新的微前端的时候,不需要构建,可以动态在代码中定义加载。我眼中的微前端更多是指这种运行时加载的微前端,因为独立构建,部署和测试是我们对于“微”的定义。

从前后端责任分层来看,可以从前端或者后端来实现。

通过客户端框架来实现

微前端通常由客户端工具来支持实现(听上去好有道理),有许多支持客户端开发微前端的实现工具,包括:Piral,Open Components,qiankun,Luigi,Frint.js等。其中qiankun是蚂蚁金服开发的。

在客户端还可以通过辅助库的方式来实现,辅助库可以为共享依赖项,路由事件或不同的微前端及其生命周期来提供一些基础架构。

下面的一个示例是通过诸如导入映射或打包特定块等机制处理共享依赖关系。

相关的工具有Webpack5 Module Federation,Siteless,Single SPA,Postal.js等

通过服务器端实现

微前端并非只能在客户端来实现,类似于服务端渲染,同样可以通过服务端来实现。

服务端微前端的支持工具有:Mosaic,PuzzleJs,Podium,Micromono等。

好了,说了这么多我相信你是一脸懵逼的,到底怎么实现的?我们抛开架构不说,来看看到底如何实现吧。

四、运行时微前端的具体实现方式

Iframe

iframes是可以在html中嵌入另一个HTML。下面就是用iframe实现微前端的一个例子:

<!DOCTYPE html>
>
>