微前端思考与总结

876

微前端是最近一年以来前端领域非常火的一个概念,同时集团内也衍生了很多相关的技术产品。这篇文章是考拉运营中台组最近调研微前端的一些尝试和思考

背景

项目:运营平台提效战役-大促盘货系统开发

业务:大促系统通过大促流程线上化,并与盘货、搭建、投放、促销等系统打通,实现大促商品、价格门槛约束和大促货品的应用,从而增强大促心智的一个系统。

我们的诉求是把大促系统打造成一个大促活动运营的门户站点,提供一站式的大促运营的解决方案,业务上会打通多个同级的系统。在这个基础上我们调研了微前端的一些技术方案。

微前端介绍

微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略micro-frontends.org

微前端工程价值

  1. 独立开发、独立部署;
  2. 框架无关;
  3. 跨业务域复用;
  4. 方便功能扩展、升级;
  5. 便于多人协作开发;

如果微前端只存在工程上的价值是不值得大张旗鼓去做的

微前端业务价值

  1. 业务原子化输出;
  2. 业务编排整合;

应用场景

  • 巨石应用的拆分-pop partner系统
  • 业务编排整合-搭建&大促系统

微前端的优势可以有效的弥补当前运营中台遇到的一些痛点:

技术:考拉入园以后有很多网易技术背景下的工程,特别是中台组这边angular和vue框架实现的代码,甚至还有前后端不分离的java+angular的老工程,这些工程开发效率慢,开发体验差,没有成就感

运营:运营同事针对各种内部系统没有统一的调配入口,一次操作有可能需要在多个不同系统完成,操作效率底下

single-spa&qiankun

single-spa是现在市场上比较成熟的技术方案,以及蚂蚁基于single-spa研发的qiankun框架

single-spa:yuque.alibaba-inc.com/kaolafed-op…

import * as singleSpa from 'single-spa';

singleSpa.registerApplication('app-1', () =>
  import ('../app1/app1.js'), pathPrefix('/app1'));
singleSpa.registerApplication('app-2', () =>
  import ('../app2/app2.js'), pathPrefix('/app2'));

singleSpa.start();

function pathPrefix(prefix) {
  return function(location) {
    return location.pathname.startsWith(`${prefix}`);
  }
}

我们需要注册对应的application,并且指定对应application的激活函数。同时application需要在入口文件导出相应的生命周期函数

export async function bootstrap(props) {...}
export async function mount(props) {...}
export async function unmount(props) {...}

image.png

如果简单来看的话,single-spa就是在合适的时候执行我们传入的loadFunctin, bootstarp, mount, unmount, unload方法,并抛出了一些事件

qiankun的启动调用方式和single-spa非常相似,但是在single-spa的基础上增加了一些功能

  1. import-html-entry
  2. js沙箱
  3. 更丰富的生命周期
  4. prefetch

qiankun.umijs.org/zh/guide/ge…

技术难点

1.应用隔离

  • js 沙箱实现

通过proxy代理window对象,监听对应的get set方法

在应用的 bootstrap 及 mount 两个生命周期开始之前分别给全局状态打下快照,然后当应用切出/卸载时,将状态回滚至 bootstrap 开始之前的阶段,确保应用对全局状态的污染全部清零。而当应用二次进入时则再恢复至 mount 前的状态的,从而确保应用在 remount 时拥有跟第一次 mount 时一致的全局上下文

image.png

  • 对象,函数劫持

setInterval、setTimeout,addEventListener,removeEventListener,appendChild

  • 单实例 多实例的场景

2.样式隔离

  • Shadow DOM
  • CSS Module? BEM
  • Dynamic Stylesheet

3.html-entry

  • 获取html页面内容
  • 解析成dom,script,style,entry入口文件
  • 获取style的内容填充到html中
  • 通过sandbox执行script代码

4.应用通信

initGloabalState,props

参考:zhuanlan.zhihu.com/p/78362028

zhuanlan.zhihu.com/p/107240132

大促系统改造方案:

主应用改造:

  • 在大促系统的工程下新建了一个服务,单独用来做微服务的主应用工程
  • 提供统一的吊顶服务
  • 因为各个系统都维护了各自独立的登录体系,主应用暴露出login入口
  • 自定义了fetch方法
  • css中相对路径替换

子应用改造:

  • 静态文件,接口请求支持跨域 egg-cors

  • 入口文件导出生命周期

  • dll output配置 library librarytarget

  • kapp/cas 去掉 loginSuccessUrl

  • mounted 增加login组件

  • 接口请求 publicpath 配置

  • 静态文件 __webpack_public

    path_

    配置

  • href 跳转替换,子应用互跳

  • 独立的路由规则

  • 隐藏侧边栏和顶栏

  • 文件上传组件publicpath设置

  • regular nej改造

www.yuque.com/docs/share/…

www.yuque.com/docs/share/…

集团其他微前端的方案

阿里云 云控制台 ConsoleOs www.atatech.org/articles/15…

菜鸟 微前端的改造方案 qiankun www.atatech.org/articles/16…

飞猪 运营工作台 qiankun www.atatech.org/articles/16…

淘系 小二工作台 icestark www.atatech.org/articles/15…

支付宝 中台业务 qiankun www.atatech.org/articles/14…

技术上的痛点:巨石应用,可维护性

  • 代码量达到一定量的时候,单次构建时间很长,开发&发布效率极低
  • 代码库中依赖升级会影响整个应用,而代码量又非常大,导致回归成本极高
  • 变成一个非常臃肿的巨石应用,完全失去灵活性,无论是多人协作还是业务接入成本都会大大增加

业务上的场景:应用的拆分和编排

  • 用户端必须是「一个系统」的心智,从域名到体验
  • 能够根据功能拆分成多个子应用,每个子应用独立开发独立部署
  • 子应用尽量保证跟传统单页面应用一样的开发体验,不要让开发者有太多学习成本
  • 所有子应用可被统一管理起来,不能无限制的泛滥

微前端生态体系?

microx microx.aliyun-inc.com/doc/hbn26z

icestark ice.alibaba-inc.com/docs/icesta…

onex bigfish.antfin-inc.com/doc/onex-ge…

什么样的模式是最佳实践?

image.png

image.png

后续规划

考拉集团内部技术栈统一

统一的配置发布平台产品,提供快速的业务整合串联能力,帮助业务提效

账号登录统一收敛

微前端子应用接入方案

包含应用 组件库 方法主应用接入方式

本地的开发工具

其他:

webpack5 module federation

webcomponent

调试

登录模式不友好

报错:ResizeObserver loop limit exceeded

image.png

image.png