介绍
MicroApp是由京东前端团队推出的一款微前端框架,它从组件化的思维,基于类WebComponent进行微前端的渲染,旨在降低上手难度、提升工作效率。MicroApp无关技术栈,也不和业务绑定,可以用于任何前端框架。
微前端是一种页面整合方案,它的核心在于将一个庞大的前端应用拆分成多个独立灵活的小型应用,每个应用都可以独立开发、独立运行、独立部署,再将这些小型应用融合为一个完整的应用,或者将原本运行已久、没有关联的几个应用融合为一个应用。微前端既可以将多个项目融合为一,又可以减少项目之间的耦合,提升项目扩展性,相比一整块的前端仓库,微前端架构下的前端仓库倾向于更小更灵活。
升级亮点
距离MicroApp开源已经有一年多时间,在这段时间里我们收到了很多问题反馈,包括沙箱的性能、vite的兼容、路由冲突等等,为了解决这些问题我们将很多核心功能进行升级和重构,经过不断的打磨和验证,最终推出MicroApp1.0正式版。
正式版的升级主要在以下几个方面:
更简洁的接入方式
沙箱的性能
虚拟路由系统
样式隔离
兼容vite
开发工具
一行代码嵌入
MicroApp借鉴了WebComponent的思想,通过CustomElement结合自定义的ShadowDom,将微前端封装成一个类WebComponent组件,实现微前端的组件化渲染。在此基础上,通过实现JS隔离、样式隔离、路由隔离,降低子应用的接入成本,子应用只需设置允许跨域请求,不需要改动任何代码即可接入微前端,使用方式和iframe几乎一致,但却没有iframe存在的问题。
接入方式如下:
JS沙箱的困境
在MicroApp开源后我们收到社区的一些反馈,其中一条关于性能的问题引起我们的重视。这不是MicroApp才存在的问题,而是微前端长久以来的难题,在社区有大量关于沙箱性能问题的讨论,却始终没有完美的解决方案。
MicroApp采用的是和qiankun一样的proxy+with的沙箱方案,这也是目前js沙箱的主流方案 。with沙箱的功能非常完善,但是性能损耗却非常明显,在社区中也不乏对with沙箱性能问题的讨论,但一直没有特别完美的解决方案,这是由于with改变了js的作用域链,从而产生大量的重复请求。问题的根源是with,但又不全是with的问题,准确的说是with和proxy两者叠加造成的,with和proxy本质上的性能都不高,需要一种方案避免对这两个方法的频繁读取操作,MicroApp采用的解决方案是变量前置和异步防抖。
• 变量前置:是指使用Object.defineProperty定义全局变量,通过get和set设置响应数据,一是为了避免在proxy的get中进行多余的操作,二是defineProperty的性能比proxy更优秀 。
• 异步防抖:是指在子应用运行时对promise进行标记,确保在上一个promise执行完成之后才会进入下一个,避免并行触发,防止promise被频繁触发会造成性能损失。
在此基础上,MicroApp沙箱还提供了快照、缓存、预加载等功能,在保证功能不变的前提下,彻底解决沙箱的性能问题,升级后的沙箱运行效率媲美原生JS。
虚拟路由系统
微前端是将多个不同的web应用融合在一起渲染,但浏览器只有一个路由系统,这很容易造成应用之间的路由冲突,最常见的就是vue3的路由冲突问题。
上面是vue-router作者对于在微前端环境下的冲突问题的回答,他认为vue-router已经覆盖足够多场景,微前端的问题应该由微前端解决。
在我们刚开源时,并没有对路由进行隔离,用户对于MicroApp的问题几乎一半都和路由相关,因为一个路由系统同时满足多个应用的渲染容易导致冲突,也非常反直觉和难以理解,于是我们推出了虚拟路由系统。
概念图:
虚拟路由系统与浏览器的路由行为一致,它通过自定义location和history等核心路由API,重写了popState和hashChange事件,拦截路由导航和事件,并提供了一系列自定义API,模拟了在浏览器环境下的Web应用程序的渲染、跳转和返回等路由行为。子应用程序在这个虚拟路由系统中运行,与基座应用程序的路由相互隔离,从而避免相互影响,并增强了子应用程序与基座应用程序之间的交互能力。通过虚拟路由系统,基座应用程序可以方便地获取子应用程序的路由信息并控制子应用程序的跳转,子应用程序的路由信息会作为参数同步到浏览器地址上。此外,虚拟路由系统还提供了许多功能,帮助开发人员提高工作效率。
样式隔离方案升级
MicroApp最初是基于style元素的CSSStyleSheet实现的样式隔离:即将CSS字符串插入style元素生成CSSStyleSheet,遍历每个CSS规则,添加前缀实现样式隔离。
这种一种取巧的方式,利用浏览器自身的能力格式化CSS,并在此基础上进行修改,省去很多工作量。但问题也出现在这里,不同浏览器对于相同的CSS生成的CSSStyleSheet可能会不同,这就导致我们在处理CSSStyleSheet会遇到不可以预知的问题,导致CSS表现不一致。
于是MicroApp换了一种方式来实现样式隔离,我们使用正则将CSS字符串切割成最小单元,每个单元包含一段CSS信息,将所有的信息整理生成CSSTree,遍历CSSTree的每个规则,添加前缀实现样式隔离。
新的方案不但抹平了不同平台间的差异,在性能上相较于旧版普遍提升30%以上,并且拥有更加灵活的配置:
/* 对指定的选择器禁用样式隔离 *
/*! scopecss-disable .test1, .test2 */
.test1 {
color: red;
}
.test2 {
color: yellow;
}
.test3 {
/* 在某一行中禁用样式隔离 */
/*! scopecss-disable-next-line */
background: url(/test.png);
}
vite的兼容
在之前的版本中,MicroApp也支持vite的接入,但必须关闭沙箱,因为vite打包出来的是esm类型的js文件,而esm无法运行在with环境中,但这样容易导致基座和子应用之间的冲突,显然是需要进一步优化的。
为此我们为vite(更准确的说是为esm类型的项目)开发了一套iframe沙箱方案,将esm类型的js文件放入iframe中运行,并通过重写子应用底层原型链的方式,实现对js和元素的拦截和处理。
iframe沙箱和with沙箱的实现方式不同,功能也略有不同,with沙箱拥有更加灵活的操作,而iframe沙箱拥有更加严格的隔离环境,两者各有优劣。用户可以在两种沙箱之间灵活切换,以满足更多特殊场景的覆盖和兼容。
Micro-App-DevTools
Micro-App-DevTools 是基于 MicroApp 推出的一款Chrome浏览器插件,目的是为了在开发和使用 MicroApp 过程中提高效率。通过此插件可以有效的解决调试困难、模拟数据通信、查看视窗范围、设置路由、获取环境变量等诉求,进而更好地帮助用户去了解和使用 MicroApp。
方案详解
Micro-App-DevTools通过模拟子应用开发环境,获取父应用数据,来可视化查看通讯数据,提高开发调试效率。对于路由,将会显示所有应用的路由,包含层层嵌套应用以及一个父应用多个子应用的路由,使不同团队应用也能快速定位自己问题,方便协作。还提供了全局变量和高亮视窗功能,实现快速定位范围,提高排查效率的功能,并集结了图标、右键、控制台的快捷进入方式,使用户快速上手,零成本使用。
总结
MicroApp 1.0已经发布,我们将积极回应开发者的问题和反馈,并持续改进,以帮助更多开发者提高效率和改善开发体验。欢迎大家使用MicroApp并参与共建,也希望在GitHub上给我们点个Star来支持我们~
MicroApp Github地址:
https://github.com/micro-zoe/micro-app
Micro-App-DevTools Github地址:
https://github.com/micro-zoe/micro-app-chrome-plugin
MicroApp官网地址:
https://micro-zoe.github.io/micro-app
作者:京东零售 马国华
来源:京东云开发者社区 转载请注明来源