你想要的【微前端】都在这里了! | 京东云技术团队
作者:京东零售 郑炳懿
开篇:
如果你不知道微前端是什么,或者不知道微前端能解决什么问题,那么你可能不需要微前端。
在我看来,对于每一个没有使用过的新技术,都应该有以下几个过程:
1、调研该技术,产出相应的调研文档。
2、输出技术Demo,基本的框架结构。
3、试着在项目中使用它,这一步坑会很多。
4、把它推动到线上完成真正的技术升级。
一、调研微前端
1.1 业务背景
某次遇到一个从0到1的大型项目,该项目涉及两个端,除了鉴权和部分业务逻辑不同外,页面UI和其余逻辑几乎一致,遇到这种项目,该如何架构?既能保证项目顺利开发完成,又能保证后期的迭代、维护、可扩展?
1.2 初步方案
首先,想到的技术方案有这么两种:
1、复用同一套代码,通过判断不同的权限,服务端下发标识,处理异同的业务逻辑。
2、开发两套代码,两套鉴权各走各的,页面相同部分从左边Copy到右边。
其次,回过头来想了想,这两种方案都有缺陷:
1、复用同一套代码,后期迭代的过程中,业务差异越来越大的时候,就会形成“屎山”。
2、开发两套代码,后期迭代的过程中,如果业务依然高度相似,那么每次都要把A项目中的代码Copy到B项目中;如果业务逐渐有了各自的风格,那么两套代码的方案显然是更佳的。
最后,除此之外,还有别的更好的方案吗?
1.3 什么是微前端?
微前端的概念是由 ThoughtWorks 在2016年提出的,它是一种前端架构风格,将一个庞大的前端应用拆分成多个独立灵活的小型应用,每个应用都可以独立开发、独立运行、独立部署,再将这些小型应用融合为一个完整的应用,或者将原本运行已久、没有关联的几个应用融合为一个应用。微前端既可以将多个项目融合为一,又可以减少项目之间的耦合,提高开发效率和可维护性。微前端的核心在于解耦,通过拆分和集成来实现前端应用的可扩展性和灵活性。
图片来源于micro-app官网
二、初识微前端
2.1 微前端能力
1、独立开发:微前端可以将一个庞大的前端应用拆分成多个小型应用,每个应用都可以独立开发,不会影响其他应用的开发进度。
2、独立部署:每个小型应用都可以独立部署,不会影响其他应用的部署进度。这也意味着可以使用不同的技术栈、不同的部署方式、不同的版本控制工具等。
3、独立运行:每个小型应用都可以独立运行,不会影响其他应用的运行状态。这也意味着可以使用不同的框架、不同的库、不同的语言等。
4、集成灵活:微前端框架可以将多个小型应用集成为一个完整的前端应用,或者将原本运行已久、没有关联的几个应用融合为一个应用。这也意味着可以根据需要动态地增加或删除应用。
5、解耦:微前端可以将前端应用拆分成多个小型应用,每个应用都有自己的职责和业务逻辑,可以减少应用之间的耦合,提高可维护性和可扩展性。
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 配置,是目前市面上接入微前端成本最低的方案。
图片来源于micro-app官网
三、应用微前端
3.1 选择 mirco-app
结合上述的调研结果,决定使用 micro-app 框架来架构我的这个大型项目。第一,micro-app 使用简单,学习成本低,小巧的体积和更高的扩展性;第二,老东家的技术,必须全力支持。
确定最终技术方案:
1、项目涉及到两个端,准备启用两个基座,这两个基座内管理鉴权和统一调用的公共逻辑,基座独立部署,属主应用。
2、项目中相同的UI部分,独立到业务组件库,可复用,业务逻辑部分,各自在项目中处理,相互独立。
3.2 启动 mirco-app
这里有详细的使用文档,就不再赘述,从引入依赖到项目完全渲染出来,只需要四步即可, micro-app 直通车。
值得一提的是第二步,有个小坑,入口处引入包,然后调用方法。
如果你的项目是 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是当前点击的菜单路径信息});
处理逻辑:
1、优先处理树形菜单,树形菜单使用递归调用,后期不管是几级菜单都不用管它了。
2、与服务端约定好树形菜单的字段,出必要字段外,应该包含对应的子应用名称,路径,icon图标等信息,这些信息是你提前给服务端,配置到表结构中的。如果项目足够大的话,可以启一个SaaS系统,更加灵活和可靠。
3、当点击菜单中对应的某个菜单时,取到当前路径拼接域名即可完成跳转。
<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 下面挂载了一个全局的对象,我们只需要去触发它提供的方法,完成主子之间的通信即可,这个逻辑想明白之后,不管是交互逻辑还是数据传递逻辑,一通都通。
3.3.3 打包问题
主子应用两个项目,在进行打包的过程,做了分包的处理,micro-app 中的js沙箱隔离技术有点小缺陷,由于主子应用使用的都是 umi 的框架,打包之后会错误的把子应用的包插入主应用中,导致应用报错,加载不出来。
处理逻辑:
// 不分割组件dynamicImport: false,
由于在实际项目操作中遇到的问题可能会比以上列举的比较多,上面举了几个典型的例子,后续大家如果使用中遇到什么问题,也可以私信我进行解决,或者留言评论。
四、总结微前端
最终我们的这个大型项目采用微前端实现了业务解耦,维护性高,扩展性高的期望,后期迭代so easy。
用起来其实还是蛮简单的,但是用好了不容易,目前我们正在规划把一整个业务线集成到微前端中,因为有些项目太老了,无法维护了,把这些老项目直接一个链接成子应用,新的迭代的都独立成一个单独的子应用,可以使用新框架,新技术去实现,技能提高开发效率,又能很好的扩展和迭代,个人觉得微前端技术很优秀,很受用。
以下是一些拆分逻辑,希望给使用微前端技术的同学一些参考:
使用微前端拆分一个大型项目需要注意以下几点:
1、拆分粒度:应该根据业务功能、团队职责、技术栈等因素来确定拆分粒度。拆分粒度太小会增加应用之间的通信成本,拆分粒度太大会影响独立开发和部署的能力。
2、拆分边界:应该确定每个小型应用的边界,使得每个应用都有自己的职责和业务逻辑。拆分边界应该尽可能地减少应用之间的耦合,同时又保证各个应用之间的协作和交互。
3、通信方式:应该确定小型应用之间的通信方式,包括接口、事件等。通信方式应该尽可能地简单和高效,同时又能够满足各个应用之间的协作和交互需求。
4、数据管理:应该确定小型应用之间的数据管理方式,包括数据共享、数据隔离等。数据管理方式应该尽可能地简单和高效,同时又能够满足各个应用之间的数据共享和隔离需求。
5、样式隔离:应该使用样式隔离技术,使得每个小型应用都可以使用自己的样式,不会影响其他应用的样式。这样可以保证各个应用之间的样式不会互相干扰,同时又不会影响应用之间的耦合。
6、集成方式:应该确定集成方式,包括微前端框架的选择、部署方式等。集成方式应该尽可能地简单和高效,同时又能够满足各个应用之间的集成需求。
总之,使用微前端拆分一个大型项目需要注意拆分粒度、拆分边界、通信方式、数据管理、样式隔离和集成方式等方面,以实现前端应用的解耦,提高可维护性和可扩展性。
相关文章:

你想要的【微前端】都在这里了! | 京东云技术团队
作者:京东零售 郑炳懿 开篇: 如果你不知道微前端是什么,或者不知道微前端能解决什么问题,那么你可能不需要微前端。 在我看来,对于每一个没有使用过的新技术,都应该有以下几个过程: 1、调研…...

人生若只如初见,你不来看看Django吗
前言 本文介绍python三大主流web框架之一的Django框架的基本使用,如何创建django项目,如何运行django项目以及django项目的目录结构,另外django又是如何返回不同的数据和页面? python三大主流web框架 Python有三大主流的web框架…...
项目人力资源管理
项目人力资源管理的 4 个过程:规划人力资源管理、组建项目团队、建设项目团队、管理项目团队等内容 单项选择题、案例分析题 人力资源管理领域输入、输出、工具和技术表: 过程名输入工具和技术输出编写项目人力资源计划 项目管理计划活动资源需求事业…...
提供接口给第三方调用,应该注意什么
1.如果我们要提供一个接口给第三方调用,首先我们需要考虑的就是接口安全,一定要做鉴权,至于鉴权的方式:大家可以在网上自行查找,今天我主要记录如何编写一个既能能支持并发的,且不会影响到我们自身业务的的…...

ESL设计概述
前言 随着芯片面临着应用场景丰富多变、集成功能模块越来越多、片内通信及模块间接口越来越复杂、设计规模越来越大以及PPA要求越来越高的需求,芯片设计方法面临越来越大的挑战。架构的合理性、完备性和一致性很大程度上决定了芯片设计的成败。基于同样的I…...

探究C语言数组的奥秘:大小可省略的定义、内存存储、数组名、传参、指针遍历、数组指针和指针数组、柔性数组等
也许你认为,C语言中的数组非常好理解,就是把一组相同类型的元素存储在同一块空间里。但是你可能并没有真正理解数组的本质,不信的话请回答一下下面的几个小问题,如果你能非常清晰的回答这些问题,那么你对C语言中的数组…...
python3 强制使用任意父级相对导入,越过python相对导入限制,拒绝 ImportError
前言 单纯不喜欢 python 对 点开头的包的限制,好麻烦,遂写了本包,来解决这个问题启用本模块后,你可以随时使用 单个点来导入当前目录的模块,也可以使用多个 点导入多级父目录内的模块,而不会报错烦人的模块…...

面了一个4年经验的测试工程师,自动化都不会也要15k,我也是醉了····
在深圳这家金融公司也待了几年,被别人面试过也面试过别人,大大小小的事情也见识不少,今天又是团面的一天, 一百多个人都聚集在一起,因为公司最近在谈项目出来面试就2个人,无奈又被叫到面试房间。 整个过程…...

Java 实现 YoloV7 人体姿态识别
1 OpenCV 环境的准备 这个项目中需要用到 opencv 进行图片的读取与处理操作,因此我们需要先配置一下 opencv 在 java 中运行的配置。 首先前往 opencv 官网下载 opencv-4.6 :点此下载;下载好后仅选择路径后即可完成安装。 此时将 opencv\b…...
跨越屏幕:桌面PC端的多端开发框架介绍
目前,随着互联网和移动互联网的发展,多端开发框架已经成为越来越多开发者更好的选择。主要有以下几个方面的前景: 跨平台开发需求不断增加:由于不同平台和设备的差异性,开发人员需要使用不同的编程语言和开发工具来为各…...
高效学习方法和工具推荐,让你事半功倍!
本文介绍了五种高效学习方法,包括制定详细的学习计划、集中注意力、不断复习、采用多种学习方式和利用小休息。同时,还推荐了五个高效学习工具和平台,包括Coursera、Duolingo、Quizlet、Khan Academy和Anki,让你在学习中事半功倍&…...
查看Docker容器中RabbitMQ的密码
要查看Docker容器中RabbitMQ的密码,可以尝试以下几个步骤: 1. 查看容器运行时的环境变量 在Docker容器中,可以通过环境变量来设置RabbitMQ的用户名和密码。因此,可以使用以下命令查看容器的环境变量: docker inspect…...
探索Qt线程编程的奥秘:多角度深入剖析
探索Qt线程编程的奥秘:多角度深入剖析 一、Qt线程编程基础(Qt Threading Basics)1.1 线程概念与基本概念(Thread Concepts and Fundamentals)1.2 Qt线程类简介:QThread(Introduction to Qt Thre…...

【R语言】鉴于计算10亿以内训练模型记录for循环的加速
文章目录 1 前言2 几个循环2.1 100以内的和2.2 100以内奇数和/偶数和 3 多重循环3.1 向量化3.2 合并循环3.3 apply函数3.4 矩阵运算3.5 foreach分解任务 4 讨论 1 前言 笔者主力机是MBAM1芯片(8256),某个下午巩固循环突然思考到个问题&#…...

C++类和对象 ——构造函数
C拷贝构造函数详解 什么是拷贝构造函数?拷贝构造函数的特征默认拷贝构造函数为什么需要显示定义构造函数?拷贝构造函数的调用场景什么时候不需要自己定义拷贝构造函数 什么是拷贝构造函数? 在现实生活中,拷贝构造函数就好像我们上…...
第2章-分治法
第2章-分治法 总分:100分 得分:20.0分 1 . 多选题 中等 10分 有关以下代码,说法正确的是( ABCE) def BinarySearch(s, x, low, high):if (low > high):return -1middle (low high) / 2if (x s[mid…...

20天能拿下PMP吗?
新版大纲,专注于人员、过程、业务环境三个领域,内容贯穿价值交付范围(包括预测、敏捷和混合的方法)。除了考试时间由240分钟变更为230分钟、200道单选题变为180道(包含单选和多选)之外,新考纲还…...

Word处理控件Aspose.Words功能演示:在 Java 中将 Word DOC/DOCX 转换为 PDF
Aspose.Words是一种高级Word文档处理API,用于执行各种文档管理和操作任务。API支持生成,修改,转换,呈现和打印文档,而无需在跨平台应用程序中直接使用Microsoft Word。 Aspose API支持流行文件格式处理,并…...

数据安全的重要性
数据安全非常重要,因为我们生活在数字化时代,许多信息和数据都以数字形式存储和传输。如果这些数据受到未经授权的访问、篡改、泄露或破坏,会对个人、组织和国家造成严重的损失。 以下是数据安全的重要性: 1. 保护各类隐私&#x…...

要创建富文本内容?Kendo UI Angular组件有专门的编辑器应对!
您的Angular应用程序可能需要允许用户添加带有格式化选项的文本、图像、表格、外观样式和/或链接,使用Kendo UI for Angular的编辑器,可以轻松搞定这些! Kendo UI for Angular是专业级的Angular UI组件库,不仅是将其他供应商提供…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...