解密微前端:"巨石应用"的诞生

随着咱们中后台系统的复杂,每每会遇到多个团队独立维护的子应用接入统一的主应用中,这些子应用每每独立开发、独立部署、彼此彻底解耦,这时候往常的单一应用没法知足业务的增加需求。而微前端即是用来解决随着时间的推移业务复杂度的提高,某个单应用演变为难以维护的“巨石应用”。css

这便文章并非一个源码解析以及上手教程的文章,我但愿从一个宏观的角度介绍下微前端而且简单聊一下微前端在咱们如今项目中的一些思考。html

先聊聊背景

我一直认为抛离业务的技术改造都是没有太大价值而且很难走远的。这里我先简单介绍下我对目前项目所作的一个架构演变以及一些简单思考。我目前所处一个大型的 B 端项目团队,系统根据业务域划分的子应用有几十个,系统 PV 百万+,因此在这样一个庞大的系统中咱们的系统架构也经历了如下一些变化。前端

模版架构

在我刚加入团队的时候,咱们的系统仍是一个先后端未彻底分离的架构,模版提供了一个入口挂载根节点,前端在根节点上渲染 React / Vue 应用。web

不难发现这样的架构存在必定的弊端:chrome

  • 后端解析模版,挂载模版;
  • 后端管控路由,前端失去了对路由的掌控权,而且多个团队路由规则管控较难;
  • 每一次前端发布须要先发布静态资源再发布模版,发布繁琐容易出错;
  • 这样的开发方式相对来讲较为古老,对于喜欢捣鼓新事物的前端来讲很难激发热情;

可是值得庆幸的是,这时候咱们的系统已经有必定的分治思想了,主应用(这个时候应该说是 layout 层)和子应用单独挂载在不一样的模版片断上,这也为后面的 iframe 和微前端改造减小了很多工做量后端

其实,这样的架构也有必定微前端的影子:) 。跨域

iframe 架构

后面随着后端微服务化的转型,后端已经不去关心路由的管控和页面的挂载,转而提供更加原子化的微服务。而对咱们前端来讲:浏览器

  • 须要不依赖后端模版;
  • 须要管控路由并制定统一的路由规则;
  • 主子应用的沙箱隔离;
  • 尽可能对子业务的改动作到最小化,不少业务包袱很重;
  • 快速落地并实现高可用(没办法,开发时间永远是一个战胜不少选项的因素...);

可是随着 iframe 架构的落地以及后续迭代的进行,咱们也发现了 iframe 方案的一些弊端:前端框架

  • 通讯方式简单,简单的 postmessage API 并不能知足业务的需求;
  • 样式割裂,iframe 会致使诸如 Dialog 这样子的全局蒙层仅在 ifame 区块内展现,使咱们系统更像是“拼凑”出来的;
  • 性能瓶颈,路由的切换会致使 iframe 内子应用的从新加载,性能堪忧;
  • 跨域问题,chrome80 的 samesite 策略会致使 iframe 方案的跨域 cookie 没法带给后端;

微前端架构

最后在今年中旬的时候我这边将 iframe 架构升级到了微前端 + iframe 并存的架构,并开发落地了一系列微前端相关的开发工具链(喜大普奔...)。cookie

so,为何不是 iframe?

在我看来,微前端是一个思想,是一种开发模式和架构的演变,诸如 qiankun、icestark 等框架也仅是微前端实现的落地,合理的 iframe 实现何尝不算是一种微前端实现的落地。咱们原来的 iframe 架构设计必定程度上也算是一种微前端思想,而且在我看来,iframe 对于这种跨团队的中后台巨无霸项目依然有着自然的优点,理由以下:

  • 框架无关:iframe 只加载部署完应用连接;
  • 独立沙箱:iframe 拥有浏览器的独立沙箱,子应用和主应用彻底不用考虑 js & css 污染问题;
  • 开发简单:仅仅一个 iframe 标签;

可是,与之而来的即是 iframe 的一些痛点:

  • UI 体验很差:iframe 仅在制定的渲染块内渲染,而子应用的一些相似于带遮罩层的 Modal 等全局的 UI 组件只会在 iframe 内呈现;
  • 通讯困难:iframe 强大的沙箱机制带来的反作用就是父子应用通讯困难,仅仅一个 postmessage API,跨域 cookie、Promise 等等都难以实现;
  • 路由丢失:子应用的 url 改变没法及时同步父应用,随着页面的刷新,子应用的路由状态丢失;
  • 加载时间长:每次子应用进入都是一次浏览器上下文重建、资源从新加载的过程;

尽管以上这些痛点或多或少的配合着一些 hack 的工具以及开发规范都有必定的解决方案,可是有更好的选择为何不尝试呢:)

那么,什么是微前端?

这里我不去讲概念,道理你们都懂,概念一搜全都是。例如微前端很官方的诠释:

Techniques, strategies and recipes for building a modern web app with multiple teams that can ship features independently

就像巨石应用并非一蹴而就的,接下来我来经过一个巨石应用的演变来向你们介绍我理解的微前端。

单个页面

起初咱们的系统可能仅有一个业务模块。路由硬编码在项目里,layout 层和业务子系统也写在一块儿。

多个页面

随着业务的增加,咱们的系统接入了更多的业务模块,这个时候其实经过必定的路由配置和多页的配置,项目也还算是没太大问题。

可是这个时候须要引发警觉,若是再接入了更多的业务模块还停留在当前的模式下,项目该怎么维护?

更多的页面?巨石应用!

随着业务更进一步的增加,接入的业务模块愈来愈多,不只咱们以导航维度扩充的子应用增多,甚至诸如首页这样子的页面上也会有归属于多个业务域的区块。总结起来就会分为两类场景:

  • 单实例:一个或多个页面对应一个子应用,同一时刻仅有一个子应用渲染展现;
  • 多实例:一个页面包含多个子业务应用区块,同一时候有多个实例渲染展现;

这时若是没有很好的处理和子系统的拆分,那么咱们的应用就会变为巨石应用...

  • 开发迭代并上线一个巨石应用比上线多个子应用要蛋疼的多...
  • 多人(多团队)维护一个项目,你永远不知作别人作了啥或者将要作啥...
  • 每每这样子的应用,你们都是作加法而不去作减法,使得项目愈来愈大,无用代码愈来愈多...

微前端,分而治之!

这时候咱们每每将系统根据业务域的划分拆分红不一样的子应用,而承载这些子应用的 layout 层咱们拆分为主应用,各个子应用独立开发独立发布,而且由不一样的业务团队维护,以此来解决复杂的单体应用带来的各类开发维护问题。

能够看出,微前端即是采起分治的思想来避免单体应用演变成巨石应用的。

在我看来,在微前端的思想中,重点强调了几点:

  • 独立性:微前端的主应用以及各个子应用独立开发、独立部署,而且在必定程度上微前端子应用能够独立于主应用单独运行;
  • 沙箱隔离:子应用有本身单独的运行时,各个子应用之间的状态不被共享;
  • 框架无关:子应用彻底能够采起不一样的框架进行开发,由于现有微前端框架实现中,主应用仅是加载子应用构建后的 bundle;

咱们的选择

如今市面上的微前端框架有不少,例如阿里内部就有 icestack、qiankun 两大比较成熟的开源微前端框架,以及社区上 singleSPA 等。那么咱们该如何选择适合咱们项目的微前端框架呢,这里我简单罗列了我在选择微前端框架时候的一些思考:

  • 改动成本:任何业务团队都不能逃避这个话题,你怎么说服产品和老板须要这么长时间的技术改造(还存在必定风险)、你怎么说服子应用方配合改造(相信我,子应用方不会愿意去作 > 1 天改造的...);
  • 沙箱隔离:这个就很少说了,不少子应用会集成本身的埋点&监控体系,这样的体系每每会挂载或者劫持全局变量的;
  • 路由不变性:在咱们 iframe 架构中,已经有一套比较完善的路由规则,那么如何保证路由不变的前提下去作架构升级呢?
  • 通讯不变性:同上,在咱们的 iframe 架构中,已经有一套比较成熟的通讯工具,那么能不能在保证 API 不变的前提下完成微前端的通讯呢?或者干脆微前端能够服用 iframe 的通讯工具?
  • 兼容 iframe:这么庞大的系统不是一会儿就迁移到微前端的,而且咱们也不打算抛弃 iframe 架构(不愿能所有业务都迁移的...)。那么,如何保证两套架构的共存?更进一步,如何保证两套架构共存而后还能共享一套路由规则?
  • 灰度控制:子应用的大版本发布每每会伴随着灰度控制,那么如何保证微前端接入后也能有完整的灰度流程?是作一个版本管控的工具仍是直接使用 htmlEntry?
  • “远古”应用接入:远古应用保持 iframe 嵌入就最好了,那么咱们能不能贪一点也能支持“远古巨龙”的丝滑接入呢?

最后,结合上面的一些思考以及咱们如今的系统架构,我选择了 qiankun 来落地咱们的微前端方案。而且为了保证微前端接入以及版本管控的便捷,咱们

结语

以上即是我在作微前端改造时候结合业务系统的一些思考,若是有不对的地方欢迎指正。以后我也会输出 qiankun 的源码解析以及我所作的一些微前端工具的原理分析等文章(撒花...)。

相关文章
相关标签/搜索