开发者社区 > 博文 > 京东微前端MicroApp上新啦!
分享
  • 打开微信扫码分享

  • 点击前往QQ分享

  • 点击前往微博分享

  • 点击复制链接

京东微前端MicroApp上新啦!

  • jd****
  • 2023-01-05
  • IP归属:北京
  • 47320浏览

    前言

    MicroApp目前已在京东集团系统以及业界其他系统中广泛应用,但在实际应用中仍发现一些需要优化的方向和问题。经过近一年的不断优化和沉淀,推出了MicroApp V1.0.0-rc版本,包含 MicroApp 核心方案、实践案例、未来规划等。感谢在此期间每一位提供反馈、建议以及贡献的人!下面把新版本主要的新增工作在此列举,具体的修改内容也可访问下面链接。

    源码地址:https://github.com/micro-zoe/micro-app 官网地址:https://zeroing.jd.com/micro-app

    关于微前端

    首先介绍下什么是微前端。微前端简单来讲,就是一种⻚面融合技术,它可以将一个庞大的巨石应用分割成独立的小型应用,同时每个应用之间又可以独立开发、独立运行、独立部署,通过微前端技术再将这些小型应用聚合为一个整体的应用,这样可以增加开发的自由、灵活性。 这对于多团队或者多人协同来共同开发一个中大型的应用是特别有用的,它可以帮助我们很好的解耦,来让不同的团队或者不同的开发者独自开发,独自发布各自负责的子应用或者子模块,然后对于用户而言,又是一个完整的系统。这样就既能保证我们的协同开发效率,又可以有很好的用户体验。所以近些年,微前端这个概念被越来越多的公司和团队所提及和应用,当然也涌现出了很多的微前端解决方案。而京东MicroApp接入成本特别的低,对子应用的几乎0侵入性,同时能,性能又很高,兼容性也极好。 下面我们来深度解析下,MicroApp最突出的核心方案。



    MicroApp核心方案

    微前端组件化

    MicroApp是大胆借鉴了 WebComponent 的思想,并以此为基础推出另一种更加组件化的微前端实现方式:类WebComponent + 虚拟路由系统。大家都知道,WebComponent 是 WEB 原生组件,它利用 shadowDOM 可以实现天然的元素隔离和样式隔离,但是 shadowDOM 的兼容性非常不好,一些前端框架在 shadowDOM 环境下无法正常运行,如 React 的全局代理事件(click)。所以我们自己实现了一套样式隔离和元素隔离方案,并将微前端应用封装在一个 CustomElement(自定义元素)中,从而模拟实现了一个类 WebComponent 组件,它的使用方式和 WebComponent 一致,同时又避开了它存在的一些问题。

    虚拟路由系统

    微前端是将多个不同的 web 应用融合在一起进行渲染的,子应用相当于页面中的一个 HTML 标签。父应用和子应用的路由页面都是依靠页面同一个页面 URL 来识别的。因此父应用和子应用路由会互相影响,而且无法适配一个父应用页面下有多个子应用情况,所以需要一种路由系统将两者路由进行隔离。

    MicroApp 就实现了一套和浏览器路由表现一致的虚拟路由系统。通过自定义 location 和 history 等核心的路由 API ,并重写了 popState 和 hashChange 事件,对路由导航以及路由事件进行拦截,并提供了一系列的自定义 API ,模拟了 Web 应用在浏览器环境下的渲染、跳转、返回等路由行为。子应用运行在这套虚拟路由系统中,和基座应用的路由进行隔离,避免相互影响,同时也加强子应用与基座之间的交互能力。通过虚拟路由系统,基座应用可以很方便的获取子应用的路由信息和控制子应用跳转。子应用的路由信息会作为参数同步到浏览器地址上。 此外虚拟路由系统还提供了丰富的功能,帮助开发者提升工作效率。包含关闭虚拟路由系统配置项、主应用与子应用之间路由跳转。

    高性能沙箱方案

    JS沙箱的困境

    在 MicroApp 开源后我们陆续收到社区的一些反馈,其中一条关于性能的问题引起我们的重视。早期MicroApp 采用的是和 qiankun 一样的 proxy + with 的沙箱方案,这也是目前js沙箱的主流方案,with 沙箱的功能非常完善,但是性能损耗却非常明显,沙箱的性能问其实是微前端领域⻓久以来的难题,在社区有大量关于沙箱性能问题的讨论,却始终没有完美的解决方案。

    团队在经历了很深度的多次讨论后,决定在 MicroApp 里创新性的实现了一套高性能的沙箱方案。我们解决沙箱性能问题的主体核心思路是:缓存 + 解耦。⼀⽅⾯ MicroApp 将全局变量进⾏了缓存,这样就能避免频繁的访问with⽅法,因为我们在分析原有沙箱⽅案的时候,发现频繁调⽤with⽅法其实是造成沙箱⽅案性能差的⼀个最主要的原因。同时 MicroApp 将 JS 变量进⾏前置以及做了异步防抖,同时⼜做到了尽可能减少proxy 的重复操作,这样⼀来就能让沙箱性能提升⼀⼤截。同时 MicroApp 进⼀步将沙箱的功能进⾏了升级,对 JS、CSS、HTML等前端静态资源进⾏了缓存,进⼀步将路由状态、⻚⾯状态就⾏了缓存,这样就能将⻚⾯产⽣的数据进⾏保存,以及将⼀些顶层变量、全局事件、定时器等操作进⾏了快照缓存来进⼀步提升沙箱的性能。在此基础上就可以实现,静态资源的预加载,HTML 以及 JS 的预解析,CSS 的预处理、以及最终的预渲染等⾼级能⼒。新的沙箱方案也在尝试解决 Es Module 的问题,将适配 Vite 等构建工具。这些都是MicroApp⾼性能沙箱提供的核⼼能⼒。


    性能对比1

    基于这些核心能力,我们也做了一些测试。在子应用中一次性插入500行每行20列的⻓列表作为测试场景,分别测试了原生 JS,MicroApp 和 qiankun 的性能,对比结果如图,大家可以看到 MicroApp 的性能相比 qiankun 提升了3倍还多,已经无线接近原生js的性能了。

    实验 Demo 已上传 Github ,详情可看 https://github.com/micro-zoe/MicroApp-sandbox-speed-test


    性能对比2

    又测试了一个另外一个场景,这是 qiankun 中讨论度很高度一个 issue ,里面有很多关于性能的问题讨论,其中有一个测试的 Demo 可以作为参 考,就是一次性渲染一万个 li 元素,我们使用这个 Demo 进行测试,结果如图所示,大家可以看到在这个场景下,MicroApp 的性能相比 qiankun 提升 了4倍还多。由此可以看出,我们的高性能沙箱方案已经无限的接近原生 JS 的水平了。

    新增配置项

    MicroApp 在老版本基础上新增了6个配置项,目前共有16个,详情可看配置文档。通过配置项,我们可以决定开启或关闭某些功能。下面将新的配置项依次列举。

    clear-data:卸载时清空数据通讯中的缓存数据。

    disable-memory-router:关闭虚拟路由系统。

    default-page:默认情况下,子应用渲染后会展示首页,设置 default-page 可以指定子应用渲染的页面。如果关闭了虚拟路由系统,default-page 也将失效。

    keep-router-state:设置 keep-router-state 可以保留子应用路由状态,在卸载后重新渲染时将恢复卸载前的页面(页面中的状态不保留)。

    disable-patch-request:默认情况下,MicroApp 对子应用的fetch、XMLHttpRequest、EventSource进行重写,当请求相对地址时会使用子应用域名自动补全。如果不需要这样的补全,可以配置disable-patch-request进行关闭,此时相对地址会兜底到主应用域名。

    fiber:默认情况下,子应用 JS 是同步执行的,这会阻塞主应用的渲染线程,当开启 fiber 后,MicroApp 会降低子应用的优先级,通过异步执行子应用的 JS 文件,以减小对主应用的影响,快速响应用户操作。


    新增全局监听

    全局监听会在每个应用的生命周期执行时都会触发。

    import microApp from'@micro-zoe/micro-app'
    microApp.start({
      lifeCycles:{
        created(e){
          console.log('created','<micro-app>标签初始化后,加载资源前触发')
        },
        beforemount(e){
          console.log('beforemount','加载资源完成后,开始渲染之前触发')
        },
        mounted(e){
          console.log('mounted','子应用渲染结束后触发')
        },
        unmount(e){
          console.log('unmount','子应用卸载时触发')
        },
        error(e){
          console.log('error','子应用渲染出错时触发,只有会导致渲染终止的错误才会触发此生命周期')
        }
      }})
    


    清空数据功能

    由于通信的数据会被缓存,即便子应用被卸载也不会清空,这可能会导致一些困扰,此时可以主动清空缓存数据来解决。

    // 清空当前子应用发送给主应用的数据
    microApp.clearData()
    // 清空主应用发送给子应用 my-app 的数据
    microApp.clearData('my-app')
    

    一行代码嵌入

    前面分别介绍了 MicroApp 性能和功能相关的很多特点,最后来讲下开发者真正使用 MicroApp 时的学习和入⻔成本,我们真正做到了 MicroApp 的标语,就是一行代码接入微前端,如同 iframe 一样简单。得益于 MicroApp 底层组件化的渲染加上虚拟路由系统,使得 MicroApp 的接入方式非常简单,只需要一行代码即可实现微前端的嵌入,而子应用只需要设置好跨域支持,不需要修改任何代码。就如同这行实例代码一样,即可轻松完成一个子应用到基座应用的嵌入。

    实践案例

    下面将以京东的营销中心作为案例来详细讲解下。京东营销中心是一个整合内部垂直平台能力的中心化工作平台,目前已经通过 MicroApp 完成了 30 多个子应用的接入,短时间内帮助业务快速将整个营销链路上各个系统进行了融合,间接节约人力80%,极大的提升了研发效能,性能非常卓越,媲美原生。MicroApp 在开源后,持续赋能不同的公司和团队。也有一些很优秀的开发者已经参与到了 MicroApp 的共建。后续我们也会持续维护 MicroApp 的开源社区生态,将 MicroApp 推给更多的团队使用,帮助大家解决微前端这个场景下的各种问题。

    未来规划

    最后,我们 MicroApp 的1.0版本即将发布,大家敬请期待,我们前面提到的种种黑科技,都会在1.0版本里开放给大家使用,欢迎大家体验。

    大家如果对 MicroApp 感兴趣,欢迎来 MicroApp 官网https://micro-zoe.github.io/micro-app/)看看,或者访问MicroApp Github 仓库https://github.com/micro-zoe/micro-app)Star 和 Fork,我们也很期待各位小伙伴前来贡献自己的一份力量。



    相关资源

    欢迎各位小伙伴一起共建京东低代码平台的其他开源项目。


    文章数
    2
    阅读量
    1410