本文不涉及具体的实现,是对过去工作的总结,只讲大体实现思路,适用于任何中台大型项目,实际项目中也涉及到移动端部分,但本文没有提及。
下面是我自己梳理的一些微前端理念需要理解的一些基本概念,多用图片表示
通过proxy创建window快照记录与恢复
1.我为什么将菜单和子容器加载的逻辑抽离出主容器基座?
项目需要管理多个子应用、MPA页面和低码开发的单个页面,同时菜单更新频繁。因此,为了避免频繁打包主容器基座来更新菜单,我需要将菜单和子应用配置抽离出基座,通过接口拉取菜单配置和子应用配置。随着菜单的膨胀,需要配置字段的增多,大JSON已经很难配置和维护了,因此我将菜单和子应用配置可视化,可视化后,产品和后端同学用起来相对得心应手。
菜单结构的设计因团队或公司而异。我的主要思路是将菜单的结构设计为menu,而将子应用的资源配置放到每个menuItem中。通过循环菜单,可以生成框架所需的appConfig资源和入口路径。在icestrak中,将路由全部设置为绝对路径,并且相同的子应用会自动匹配资源。这样的设计可以更加灵活地配置菜单和子应用,同时也方便了框架的使用和维护。
菜单字段设计依据下面3方面:
上面已经初步搭建完成的微前端体系,但当你跑起一个子应用demo的时候,会发现比自己开发spa应用要慢,这里就要说说微前端应用的渲染体系。
当前的渲染顺序
从上图可以看出,子应用资源的加载时机相比于spa应用延后的特别多,渲染就会比传统spa应用慢很多,下面是我的两个优化思路
在全局大图中,有一个pre-effect的脚本,第三部分就是上面问题的优化思路,前置子应用资源的加载时机,,在加载主容器资源之前就通过逻辑匹配确定子应用的资源,用浏览器的预请求和资源并发机制,提前把首次进入的子应用资源加载好(依据子应用的资源大小提高首屏LCP200ms~400ms不等)
随着接入的子应用越来越多,菜单膨胀到几千行,此时通过接口拉取菜单JSON配置后,再去生成对应的菜单和appConfig耗时可能超过400ms,微前端应用会出现渲染子应用卡白屏的瞬间,为此,和负责开发网关同学沟通,在生成vm模版时,直接注入到window上全局菜单,引入菜单版本概念,菜单解析完成生成的headermenu和sildermenu和appConfig保存到本地indexDb里,window注入的菜单版本和本地不同,运算一遍菜单生成逻辑,更新indexDB里。
当子应用的资源加载后,初始化子应用项目时,可能会有一些需要通过拉取接口数据后才能初始化完成的子spa应用(比如某些页面需要用户的鉴权状态,某些页面加载前可能需要拉取一些关键接口才能渲染等情况),这个初始化的过程会阻塞子应用的渲染,提取这部分初始化接口逻辑到主容器中,并发的调取首次进入的子应用初始化的所需接口,通过webWorker处理,挂载到对应字应用的全局chidlrenConfig上。(优化结果提高200ms到300ms不等)
9个项目历史跨度巨大,所有融合子项目都要做request改造,子应用处于微应用模式下,子应用统一调用公共请求,封装统一错误处理(统一公共组件ui抛出),增加频繁更新接口缓存机制,设计单项目连续错误上报机制。
抽离出来的逻辑和接口,根据子应用初始化逻辑复杂度不等,充分利用浏览器并发机制和通过webWorkder计算不占据主容器渲染线程,,首屏LCP提升100ms~400ms。
....
主容器里的i18n标是全局唯一i18n标,子应用的i18n标记跟随主容器刷新,并且负责判定子容器加载zh/en的language语言包,子应用组件国际化跟随容器标记重置。(子应用使用的i18n各不相同,根据全局I18n标识各自强制刷当前页面才可重置成功),这里是否有别的方案,国际化切换时候体感并不是很好,切换国际化后每个子应用都要强制刷新一遍页面,除了使用相同i18nde框架还有别的办法吗?
使用@ice/stark-data设计全局通信体系,初始化一些全局公共接口数据到iceStore里。
中台管理系统右侧slot一般有消息通知模块,用户信息模块,全局功能搜索模块和帮助中心模块。当前主容器基座的设计如果只用在自己的项目中,付出这么多心血其实不值得,如果可以把当前容器设计成企业统一的微前端容器来使用,右侧功能栏的插槽化设计就是最优方案。
这一块实现比较多,需要有动态配置包的能力。总体思路是将右侧slot抽离成plugin,封装成可插入的plugin插件,vm初始化时候注入相应的脚本路径和脚本名称,子应用加载后执行插槽的渲染。
在微前端体系改造中,子应用的改造是工作量最大和最复杂的部分。这是因为一些旧的构建工具已经过时,无法满足改造的需求,一些依赖的包也是基于Node8开发的,无法升级到最新版本,这给升级工作带来了很大的困难。因此,升级的过程变得费时费力。需要采取措施来解决这些问题,如引入新的构建工具、逐步更新依赖的包等,以确保子应用能够顺利地进行工程化改造。同时,需要认识到这是一个长期的过程,需要耐心和不断地优化和迭代。
总体思路:保留原本老站点,使用一套代码,增加umd打包格式。工程改造为微前端启动和原有端形式启动,线上资源部署会分为spa打包模式和微前端打包模式,分别独有资源版本号。
子应用改造如何融入微前端体系没有标准的方案,很多策略依据自己的项目情况而定。
简单列举一些子应用改造中的难点
{"build:mfa":"REACT_APP_ENV=mfawepbackbuild","build":"wepbackbuild","start:mfa":"REACT_APP_ENV=mfawepbackstart","start:mfa":"wepbackstart",}线上构建拿取环境信息中的version注入到编译环境中,确定完整cdn路径commandecho$BUILD_ARGV_STR|sed\"s/.*--version=\\(\\S\\+\\).*/\\1/g\"spa子应用性能优化大致说一些优化思路和方向
微前端体系让mpa应用重新占据优势,新页面都通过mpa应用打包生成单页面引入微前端体系。