你想要的【微前端】都在这里了!

Tech 导读
如果你不知道微前端是什么,或者不知道微前端能解决什么问题,那么你可能不需要微前端。
本文认为,对于每一个没有使用过的新技术,都应该有以下几个过程:
1、调研该技术,产出相应的调研文档。
2、输出技术Demo,基本的框架结构。
3、试着在项目中使用它,这一步坑会很多。
4、把它推动到线上完成真正的技术升级。
导读
如果你不知道微前端是什么,或者不知道微前端能解决什么问题,那么你可能不需要微前端。
本文认为,对于每一个没有使用过的新技术,都应该有以下几个过程:
1、调研该技术,产出相应的调研文档。
2、输出技术Demo,基本的框架结构。
3、试着在项目中使用它,这一步坑会很多。
4、把它推动到线上完成真正的技术升级。
1.1 业务背景
某次遇到一个从0到1的大型项目,该项目涉及两个端,除了鉴权和部分业务逻辑不同外,页面UI和其余逻辑几乎一致,遇到这种项目,该如何架构?既能保证项目顺利开发完成,又能保证后期的迭代、维护、可扩展?
1.2 初步方案
最后,除此之外,还有别的更好的方案吗?
1.3 什么是微前端?
2.1 微前端能力
6、增量升级:微前端可以实现增量升级,只需要升级需要更新的小型应用,而不需要升级整个前端应用。这可以减少升级带来的风险和成本。
2.2 微前端核心
1、拆分:将前端应用拆分成多个小型应用,每个应用都有自己的职责和业务逻辑。这样可以减少应用之间的耦合,使得每个应用都可以独立开发、独立部署和独立运行。
2、集成:通过微前端框架将多个小型应用集成为一个完整的前端应用。这样可以根据需要动态地增加或删除应用,实现灵活的集成。
3、通信:通过定义接口和事件等方式,实现小型应用之间的通信。这样可以保证各个应用之间的协作和交互,同时又不会影响应用之间的耦合。
4、样式隔离:通过使用样式隔离技术,使得每个小型应用都可以使用自己的样式,不会影响其他应用的样式。这样可以保证各个应用之间的样式不会互相干扰,同时又不会影响应用之间的耦合。
总之,微前端的核心是解耦,通过拆分、集成、通信和样式隔离等方式,实现前端应用的解耦,提高可维护性和可扩展性。
2.3 微前端平台
1、single-spa是一个将多个单页面应用聚合为一个整体应用的 JavaScript 微前端框架。
2、qiankun 蚂蚁金服出品,基于 single-spa 封装的微前端框架。
3、MicroApp 京东出品,一款基于WebComponent的思想,轻量、高效、功能强大的微前端框架。
由于项目使用的 umi + react +ts 的技术栈,而 qiankun 天生就集成在 umi 框架中了,只需要一些配置就可以使用微前端技术,注意,这里所说的是一些配置,就是这一些配置,使本次项目使用中放弃了 qiankun 微前端框架,因为 single-spa 要求子应用修改渲染逻辑并暴露出三个方法:bootstrap、mount、unmount,分别对应初始化、渲染和卸载,这也导致子应用需要对入口文件进行修改。而 qiankun 是基于single-spa进行封装,所以这些特点也被 qiankun 继承下来,并且需要对 webpack 配置进行一些修改,成本相对较高。
再来看 micro-app 老东家出品的微前端框架,借鉴了 WebComponent 的思想,通过 CustomElement 结合自定义的 ShadowDom,将微前端封装成一个类WebComponent 组件,从而实现微前端的组件化渲染。并且由于自定义ShadowDom的隔离特性,micro-app不需要像single-spa和qiankun一样要求子应用修改渲染逻辑并暴露出方法,也不需要修改 webpack 配置,是目前市面上接入微前端成本最低的方案。
图2.micro-app微前端框架,来源于micro-app官网
应用微前端
3.1选择 mirco-app
结合上述的调研结果,决定使用 micro-app 框架来架构这个大型项目。第一,micro-app 使用简单,学习成本低,小巧的体积和更高的扩展性;第二,老东家的技术,必须全力支持。
确定最终技术方案:
1、项目涉及到两个端,准备启用两个基座,这两个基座内管理鉴权和统一调用的公共逻辑,基座独立部署,属主应用。
2、项目中相同的UI部分,独立到业务组件库,可复用,业务逻辑部分,各自在项目中处理,相互独立。
3.2 启动 mirco-app
这里有详细的使用文档,就不再赘述,从引入依赖到项目完全渲染出来,只需要四步即可, micro-app 直通车:https://zeroing.jd.com/docs.html#/zh-cn/start
值得一提的是第二步,有个小坑,入口处引入包,然后调用方法。
如果你的项目是 Vue的话,这里说的入口文件应该是 main.js;如果你的项目是 umi 框架的话,入口文件指的的是 src/pages/.umi/umi.js 文件,这个文件是 umi 自动生成的,无法让你在这里面编码,所以你需要在 src 目录下面新建一个 index 或者 global 的文件,把下面的代码复制进去。
// 项目入口处引入import microApp from '@micro-zoe/micro-app'microApp.start()
按照文档的指引,你应该看到这个界面,如果没有看到这个界面,那说明你的姿势有问题,可能是跨域导致,关于跨越问题,Q&A里面有解决方案,用《程序员的修炼之路》中的一句话来说:“读一下那些该死的报错信息”,没准你就能启动成功了。
3.3 踩坑 micro-app
3.3.1 路由问题
项目启动起来要面对的第一个问题就是路由问题。案例里面给的菜单是一级菜单,但是实际项目应用中可能有二级、甚至三级菜单,那怎么匹配路由跳转到对应的子应用呢?
microApp.router.push({name: 'pop', // 子应用名称path: `${config.pop}${item.url}` // config是配置文件 item是当前点击的菜单路径信息});
<micro-appname="pop"url={config?.pop}/>
3.3.2 面包屑问题
强烈建议把面包屑放到子应用中,面包屑在子应用中的好处是自由完成跳转,不用主应用做特别的处理,唯一需要处理的是面包屑里面的首页,因为面包屑放到子应用中,点击回首页时,回到的其实是子应用的首页,并非是主应用的首页。
主应用处理逻辑:
import React from 'react';import config from '@/config';/** @jsxRuntime classic *//** @jsx jsxCustomEvent */import jsxCustomEvent from '@micro-zoe/micro-app/polyfill/jsx-custom-event';export default ():React.ReactElement => {// 子应用点击了面包屑的回到首页const onDispathChild = (e:any) => {const { isBackHome } = e.detail.data;if (isBackHome) window.location.href = '/';};return (<><micro-appname="pop"url={config?.pop}default-page={`${config?.pop}${config.defaultUrl}`}onDataChange={onDispathChild}/></>);};
子应用逻辑:
// 点击回到首页的时候,需要告诉父应用,让父应用去重置路由const onBackHome = () => {window.microApp?.dispatch({ isBackHome: true });};
micro-app 在 window 下面挂载了一个全局的对象,只需要去触发它提供的方法,完成主子之间的通信即可,这个逻辑想明白之后,不管是交互逻辑还是数据传递逻辑,一通都通。
处理逻辑:
// 不分割组件dynamicImport: false,
由于在实际项目操作中遇到的问题可能会比以上列举的比较多,上面举的是几个比较典型的例子。
最终这个大型项目采用微前端实现了业务解耦,维护性高,扩展性高的期望,后期迭代so easy。
用起来其实还是蛮简单的,但是用好了不容易,目前正在规划把一整个业务线集成到微前端中,因为有些项目太老了,无法维护了,把这些老项目直接一个链接成子应用,新的迭代的都独立成一个单独的子应用,可以使用新框架,新技术去实现,技能提高开发效率,又能很好的扩展和迭代,于是有些人觉得微前端技术很优秀,很受用。
总之,使用微前端拆分一个大型项目需要注意拆分粒度、拆分边界、通信方式、数据管理、样式隔离和集成方式等方面,以实现前端应用的解耦,提高可维护性和可扩展性。
求分享
求点赞
求在看
▪功能支撑:会员成长体系、等级计算策略、权益体系、营销底层能力支持
▪用户活跃:会员关怀、用户触达、活跃活动、业务线交叉获客、拉新促活