莫方教程网

专业程序员编程教程与实战案例分享

微前端五大门派大 Battle_微前端技术

前言:本文着眼于梳理业界微前端技术(介绍下微前端几场恶仗的主打人)的发展脉络、在主流产品中的应用情况,以及目前不同技术方案之间的架构和核心原理对比,只关注精华部分,不纠结于技术细节,帮大家快速建立起对微前端整体上的认识。

注:相信本文对各个微前端方案的总结是相对全面的,但缺点是对每个方案深入了解的程度有限,难免有错误和遗漏之处,欢迎大家评论勘误和补充!也欢迎大家通过我提供的索引,选择自己感兴趣的方向继续深入学习。

  1. 微前端简介
  1. 什么是微前端?

相信大家对此已经耳熟能详,我就不多废话了,直接摘一段词条解释。

微前端是一种由独立交付的多个前端应用组成整体的架构风格,将前端应用分解成一些更小、更简单的能够独立开发、测试、部署的应用,而在用户看来仍然是内聚的单个产品。

此外,Martin Fowler 还给过一个更简洁的英文解释:

An architectural style where independently deliverable frontend applications are composed into a greater whole.

厘清一些关于微前端概念的误区

  • 微前端不是一门具体的技术,而是整合了技术、策略和方法,可能会以脚手架、配套工具和规范约束等等成体系的形式综合呈现,是一种宏观上的架构。这种架构目前有多种方案,各有利弊,但只要适用业务场景的就是好方案。
  • 微前端本身并没有技术栈的约束(技术栈无关不是微前端的固然要求)。每一套微前端方案的设计,都是基于实际需求出发。如果是多团队统一使用了 React 技术栈,可能对微前端方案的跨技术栈使用并没有要求;如果是多团队同时使用了 React 和 Vue 技术栈,可能就对微前端的跨技术栈要求比较高。
  • 微前端要求各个应用能独立开发、测试、部署,但并不要求各个应用能独立运行。也就是说,微前端的粒度不一定是应用级的,也有可能是页面级,甚至组件级。
  1. 微前端的发展

“微前端(Micro Frontends)”这个概念由 thoughtworks 于 2016 年 11 月在 TECHNOLOGY RADAR 文章中率先提出。经过 5 年的发展,现在我随便一列,实现微前端的主流方案就已经多达 20 多种,实现的方式也是五花八门,至于应用微前端技术的产品之多,那就更数不清了。

就这个成果来看,当时的想法可以说是非常具有前瞻性。

如果再往前追溯,“微前端”其实是受到了 2014 年正式提出的“微服务(Microservices)”概念的启发。

微服务是指一种软件架构风格,以专注于单一责任与功能的小型功能区块 (Small Building Blocks) 为基础,利用模块化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关 (
Language-Independent/Language agnostic)的 API 集相互通信。

  • 技术上:
    • “微前端”和“微服务”需要解决的问题是共通的(你看,连定义都是这么相像...),简单说起来就是:应用随着项目迭代越来越庞大,耦合度升高,以致缺乏灵活性,难以维护。
  • 团队协作上:
    • 康威定律指出,设计系统的架构受制于产生这些设计的组织的沟通结构。它指出了组织架构越庞大,其系统间沟通成本越高的问题。
    • 解决这一问题的有效手段就是,将大的系统拆分成一个个微小的,可以独立自治的子系统。一旦系统的依赖限制在了内部,功能上更加内聚,对外部的依赖变少,那么就能显著的减少跨系统之间的沟通成本了。
    • 简单来说,康威定律的指导思想就是:既然沟通是大问题,那么就不要沟通就好了。所以,微前端(微服务架构)也关注如何解决组织和团队间协作带来的工程问题,而不是单纯的某个技术问题。
  • 而在业务上:
    • 选择前端微服务化的原因却刚好与“解耦”、“拆分”相反——人们更想要的结果是聚合,尤其是那些 To B 的应用。比如大家熟悉的各类云服务网站、以及大部分的中台应用。
    • 在“聚合”这一目标上,面临的另一个重大困难来自遗留系统。在既不重写原有系统的基础之下,又可以抽出人力来开发新的业务,对于业务和技术人员来说, 是一个相当吸引力的特性。这也是微前端大受欢迎的主要原因之一。
  1. 微前端历史演进图

单体应用 -> 前后端分离 -> 微服务化 -> 微前端化。

  1. 微前端背后的核心思维
  • 技术不可知主义
    • 每个团队应该选择自己的技术栈以及技术进化路线,而不是与其他团队步调一致。
  • 隔离团队之间的代码
    • 即便所有团队都使用同样的框架,也不要共享同一个运行时环境。构建自包含的Apps。不要依赖共享的状态或者全局变量。
  1. 微前端的实现要求(评价标准)

是不是一个微前端实现方案,和是不是一个好的微前端实现方案——这是两个不同的问题。

判断一个微前端是否优秀(符合需求)和全面,可以从以下维度进行评价分析:

  1. 微前端的呈现方式

典型的微前端看起来大致可以分为两种:

  1. 按布局呈现

举例,主应用(上图 Menu&Header 部分)负责路由、账号管理等公共功能模块,子应用(Content&Footer 部分)承载业务逻辑。这也是我们在生产中常见的微前端的呈现。

  1. 按领域呈现
  1. 中台应用的开发者可能对上面按布局划分的微前端更加熟悉,但真实世界是更复杂的。比如商城应用,不同团队可能负责页面的不同模块,比如产品、推荐、结算模块等,在页头、侧边栏部分淡化了主从关系。

总结而言,在微前端的设计中,拆分应该更多地根据业务需求来做,而不是技术决策。领域驱动设计(Domain-Driven Design,简称DDD),也应该是微前端分解的准则。

  1. 微前端的集成方式
  1. 微前端的体系

前文提到微前端不只是一门具体的技术,而往往是一套体系。在目前主流的 production-ready 的微前端方案中(主要集中在下文定义的庄重稳健老干部派),这套体系大致可分为如下几个部分:

  1. 治理体系

「治理体系」简单看可以视为一个上线管理平台 + 上线发布流程。业界的管理平台大体实现这两个功能:

  • 应用管理 - 能上线各种主应用、子应用不同版本,列出上线应用不同版本的入口地址
  • 依赖管理 - 明确管理父子应用依赖关系,将子应用入口地址注入父应用
  1. 开发配套

这一部分比较容易理解:给开发者提供完整的文档指引是必备项。

  1. 微物料

微物料将微前端的粒度级别从应用级别延伸到了组件、函数级别。

  • App: 一整个微前端应用,内部也能有很多模块、多个页面 (Page)。
  • Page: 一个稍大一点有路由的微前端组件可以称为页面,如一个数据查询页面。
  • Widget 没有路由的小组件(挂件),如一个样式很独特的按钮。
  • Function: 被远程加载执行的一个功能函数,如试想一下用 UMD 加载 lodash 一个 func (接口格式定义在应用外)。
  1. 运行时容器

这部分是狭义上的「微前端框架」所做的事,具体原理将在下文分析。

  1. 微前端的批评意见

微前端的主要批评意见集中在其热度很高的情况下,开发者将微前端视作完美的解决方案,“热闹驱动开发”,而脱离了实际业务需求和对微前端收益、成本、缺点的综合评估。

满足以下几点,你可能就不需要 微前端 ?:

  1. 你/你的团队具备系统内所有架构组件的话语权:简单来说就是,系统里的所有组件都是由一个小的团队开发的。
  2. 你/你的团队有足够动力去治理、改造这个系统中的所有组件:直接改造存量系统的收益大于新老系统混杂带来的问题。
  3. 系统及组织架构上,各部件之间本身就是强耦合、自洽、不可分离的。系统本身就是一个最小单元的「架构量子」,拆分的成本高于治理的成本。

满足以下几点,你才确实可能需要 微前端 ?:

  1. 系统本身是需要集成和被集成的,一般有两种情况:
    1. 旧的系统不能下,新的需求还在来。
    2. 系统需要有一套支持动态插拔的机制。
  2. 系统中的部件具备足够清晰的服务边界。

微前端的其他批评意见来自其自身的固有缺点,比如:

  • 系统复杂度
  • 性能(体积大小)
  • 额外问题的不可预见性

总结:一切都是权衡。


  1. 主流技术方案对比(五大门派间不得不说的故事)

这五大门派只是大致的划分,它们之间并非水火不容, 而是对彼此的理念、核心技术均有一定程度的参考和应用

  1. iframe:Old school 死磕派

HTML 内联框架元素

跳转

调用 activate 方法,可以跳转到 src 中的页面

不可跳转

路由

标签里的页面操作路由,路由变化可反映到地址栏

路由变化无法在父、子应用中同步

浏览上下文

总是在 top-level; 标签的浏览上下文属于一个单独的浏览上下文组,所以有单独的事件循环,即使是同源

嵌套在树中;同源