在一瞬间有一千万种可能......

在一瞬间有一千万种可能......

一、微前端概述

1.  什么是微前端?

  为了解决庞大的一整块后端服务带来的变更与扩展方面的限制,出现了微服务架构。然而,越来越重的前端工程也面临同样的问题,自然地想到了将微服务思想应用(照搬)到前端,于是有了“微前端(micro-frontends)”的概念。即,一种由独立交付的多个前端应用组成整体的架构风格。具体的,将前端应用分解成一些更小、更简单的能够独立开发、测试、部署的小块,而在用户看来仍然是内聚的单个产品。

  我们常见后台项目通常长这样:

 微前端开发(Vue)-LMLPHP

  如果我们的项目需要开发某个新的功能,而这个功能另一个项目已经开发好,我们想直接复用时。

  说明我们需要的只是别人项目的这个功能页面的内容部分,不需要别人项目的顶部导航和菜单。

一个比较笨的办法就是直接把别人项目这个页面的代码拷贝过来,但是万一别人不是 vue 开发的,或者说 vue 版本、UI 库等不同,以及别人的页面加载之前操作(路由拦截,鉴权等)我们都需要拷贝过来,更重要的问题是,别人代码有更新,我们如何做到同步更新。甚至当别的项目采用其它技术栈时,如何集成?显然复制代码是行不通的。

  以前端组件的概念作类比,我们可以把每个被拆分出的子应用看作是一个应用级组件,每个应用级组件专门实现某个特定的业务功能(如商品管理、订单管理等)。这里实际上谈到了微前端拆分的原则:即以业务功能为基本单元。经过拆分后,整个系统的结构也发生了变化:

 微前端开发(Vue)-LMLPHP

  如上图所示,左侧是传统大型单页应用的前端架构,所有模块都在一个应用内,由应用本身负责路由管理,是应用分发路由的方式;而右侧是基座模式下的系统架构,各个子应用互不相关,单独运行在不同的服务上,由基座应用根据路由选择加载哪个应用到页面内,是路由分发应用的方式。这种方式使得各个模块的耦合性大大降低,而微前端需要解决的主要问题就是如何拆分和组织这些子应用。

典型的基于vue-routerVue应用与这种架构存在着很大的相似性:

微前端开发(Vue)-LMLPHP

2.  巨无霸项目的存在的问题

  • 代码越来越多,打包越来越慢,部署升级麻烦,一些插件的升级和公共组件的修改需要考虑的更多,很容易牵一发而动全身
  • 项目太大,参与人员越多,代码规范比较难管理,代码冲突也频繁。
  • 产品功能齐全,但是客户往往只需要其中的部分功能。剥离不需要的代码后,需要独立制定版本,独立维护,增加人力成本。

  微前端的诞生也是为了解决以上问题:

  •   复用(嵌入)别人的项目页面,但是别人的项目运行在他自己的环境之上。
  •   巨无霸应用拆分成一个个的小项目,这些小项目独立开发部署,又可以自由组合进行售卖。

  使用微前端的好处:

  •     技术栈无关,各个子项目可以自由选择框架,可以自己制定开发规范。
  •    快速打包,独立部署,互不影响,升级简单。
  •    可以很方便的复用已有的功能模块,避免重复开发。

二、常见微前端方案

  目前主流的微前端方案包括以下几个:

  •  iframe
  • 基座模式,主要基于路由分发,qiankunsingle-spa就是基于这种模式
  • 组合式集成,即单独构建组件,按需加载,类似npm包的形式
  • EMP,主要基于Webpack5 Module Federation
  • Web Components

  iframe:是传统的微前端解决方案,基于iframe标签实现,技术难度低,隔离性和兼容性很好,但是性能和使用体验比较差,多用于集成第三方系统;

  基座模式:主要基于路由分发,即由一个基座应用来监听路由,并按照路由规则来加载不同的应用,以实现应用间解耦;

  组合式集成:把组件单独打包和发布,然后在构建或运行时组合。

  EMP:基于Webpack5 Module Federation,一种去中心化的微前端实现方案,它不仅能很好地隔离应用,还可以轻松实现应用间的资源共享和通信

  Web Components:是官方提出的组件化方案,它通过对组件进行更高程度的封装,来实现微前端,但是目前兼容性不够好,尚未普及。

  总的来说,iframe主要用于简单并且性能要求不高的第三方系统;组合式集成目前主要用于前端组件化,而不是微前端;基座模式、EMPWeb Components是目前主流的微前端方案。

  目前微前端最常用的有两种解决方案:iframe 方案和 基座模式方案

1.  iframe方案

  iframe 大家都很熟悉,使用简单方便,提供天然的 js/css 隔离,也带来了数据传输的不便,一些数据无法共享(主要是本地存储、全局变量和公共插件),两个项目不同源(跨域)情况下数据传输需要依赖 postMessage

  iframe 有很多坑,但是大多都有解决的办法:

  1. 页面加载问题

  iframe 和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载,阻塞 onload 事件。每次点击都需要重新加载,虽然可以采用 display:none 来做缓存,但是页面缓存过多会导致电脑卡顿。(无法解决)

  2. 布局问题

  iframe 必须给一个指定的高度,否则会塌陷。

  解决办法:子项目实时计算高度并通过 postMessage 发送给主页面,主页面动态设置 iframe 高度。有些情况会出现多个滚动条,用户体验不佳。

  3. 弹窗及遮罩层问题

  弹窗只能在 iframe 范围内垂直水平居中,没法在整个页面垂直水平居中。

  解决办法1:通过与框架页面消息同步解决,将弹窗消息发送给主页面,主页面来弹窗,对原项目改动大且影响原项目的使用。

  解决办法2:修改弹窗的样式:隐藏遮罩层,修改弹窗的位置。

  4. iframe 内的 div 无法全屏

  弹窗的全屏,指的是在浏览器可视区全屏。这个全屏指的是占满用户屏幕。

  全屏方案,原生方法使用的是 Element.requestFullscreen(),插件:vue-fullscreen。当页面在 iframe 里面时,全屏会报错,且 dom 结构错乱。

  解决方案:iframe 标签设置 allow="fullscreen" 属性即可

  5. 浏览器前进/后退问题

  iframe 和主页面共用一个浏览历史,iframe 会影响页面的前进后退。大部分时候正常,iframe 多次重定向则会导致浏览器的前进后退功能无法正常使用。并且 iframe 页面刷新会重置(比如说从列表页跳转到详情页,然后刷新,会返回到列表页),因为浏览器的地址栏没有变化,iframe src 也没有变化。

  6. iframe 加载失败的情况不好处理

  非同源的 iframe 在火狐及 chorme 都不支持 onerror 事件。

  解决办法1onload 事件里面判断页面的标题,是否 404 或者 500

  解决办法2:使用 try catch 解决此问题,尝试获取 contentDocument 时将抛出异常。

2.  基座模式方案

  基座模式方案以single-spaqiankun为代表,这里我选择qiankun

  qiankun 是蚂蚁金服开源的一款框架,它是基于 single-spa 的。他在 single-spa 的基础上,实现了开箱即用,除一些必要的修改外,子项目只需要做很少的改动,就能很容易的接入。

  qiankun框架官网:https://qiankun.umijs.org/zh/

  微前端中子项目的入口文件常见的有两种方式:JS entry HTML entry。 single-spa 采用的是 JS entry,而 qiankun 既支持 JS entry,又支持 HTML entry

  JS entry 的要求比较苛刻:

  (1)将 css 打包到 js 里面

  (2)去掉 chunk-vendors.js

  (3)去掉文件名的 hash

  (4)将 single-spa 模式的入口文件( app.js )放置到 index.html 目录,其他文件不变,原因是要截取 app.js 的路径作为 publicPath

  建议使用 HTML entry ,使用起来和 iframe 一样简单,但是用户体验比 iframe 强很多。qiankun 请求到子项目的 index.html 之后,会先用正则匹配到其中的 js/css 相关标签,然后替换掉,它需要自己加载 js 并运行,然后去掉 html/head/body 等标签,剩下的内容原样插入到子项目的容器中

二、微前端方案实践

  以“大数据分析”项目为例,将客户特有的需求,如“电子路单”、“数据填报”单独提取为可独立运行的子项目。

  大数据分析项目改造为主应用基座,代码仓库地址:http://192.168.1.102/zouqiongjun/big-data-web.git

  客户自定义需求单独作为子应用项目,代码仓库地址:http://192.168.1.102/zouqiongjun/zibo-custom-web.git

1.  各应用工程代码结构

  sass-base-web:主仓库,主要存放一些批量操作的脚本,用于聚合管理仓库和一键编译、一键部署。

  仓库代码结构如下图所示:

微前端开发(Vue)-LMLPHP 

  big-data-web:大数据分析主应用

  zibo-custom-web:客户自定义需求,微应用仓库

  子应用可以独立运行,但是当前子应用是直接嵌套在主应用的main内容区域,所以暂时并没有单独提供左侧菜单导航,后续如有需要可以扩展和补充此功能。

2.  主应用big-data-web改造

  将普通的项目改造成 qiankun 主应用基座,需要进行三步操作:

  (1) 创建微应用容器 - 用于承载微应用,渲染显示微应用;

  (2) 注册微应用 - 设置微应用激活条件,微应用地址等等;

  (3) 启动 qiankun

  注意:由于big-data-web主应用的路由采用的是hash模式,所以子应用的路由也应该采用hash模式。

1.1 安装 qiankun

$ yarn add qiankun # 或者 npm i qiankun -S
10-29 20:02