大白话:
使用主应用加载子应用的方式,将子应用作为一个独立的模块进行加载和管理。主应用充当着一个容器的角色,负责管理和控制子应用的生命周期、理由、状态等信息,子应用则专注于业务逻辑的开发,这种方式可以有效的隔离子应用之间的影响,使得不同的子应用可以使用不同的技术栈和框架,从而提升了整个应用的灵活性和可扩展性。
官话
qiankun继承了single-spa的特点,通过监听hashChange和popState这两个原生事件来检测路由变化,在路由变化时匹配到需要渲染的子应用,去加载子应用的HTML,先检查是否有缓存,如果有,直接从缓存中返回并进行渲染,如果没有则通过fetch函数去下载配置的html入口、并返回字符串,通过process函数处理字符串、返回模版、外联脚本、外联样式、和应用入口脚本。调用getEmbedHTML把外联的样式下载下来,并替换到模板内,使其变成内部样式。
同时子应用需要在入口文件中暴露出三个方法:bootstrap、mount、unmount,使得主应用能识别对应的子应用,并且需要在打包时将webpack的publicPath进行修改。
详细原理如下:
1. 路由
【1】single-spa是通过监听hashChange和popState这两个原生事件来检测路由变化的
【2】当路由变化时,single-spa会监听到,并触发urlReroute
【3】接着它会调用reroute,该函数正确设置各个应用的状态后调用getAppChanges获取 待清除、待卸载、待加载、待挂载4种不通状态下应用的数据。
【4】对不同的数组执行不同的生命周期方法。
流程图如下:
2、应用入口
只要你的应用实现了 bootstrap 、mount 和 unmount 三个生命周期钩子,有这三个函数导出,我们的框架应用就可以知道如何加载这个子应用。这三个钩子也正好是子应用的生命周期钩子。当子应用第一次挂载的时候,我们会执行 bootstrap 做一些初始化,然后执行 mount 将它挂载。当你应用切换走的时候,我们会执行 unmount 把应用卸载掉。
3、应用加载
qiankun采用的应用加载是在运行时通过加载子应用的HTML。
【1】检查是否有缓存,如果有,直接从缓存中返回
【2】如果没有则通过fetch函数去下载配置的html入口、并返回字符串
【3】通过process函数处理字符串、返回模版、外联脚本、外联样式、和应用入口脚本。
【4】调用getEmbedHTML把外联的样式下载下来,并替换到模板内,使其变成内部样式
【5】返回一个对象,该对象包含处理后的模板,以及getExternalScripts、getExternalStyleSheets、execScripts等几个核心方法。
应用加载及process函数处理流程图:
4、JS隔离
qiankun的隔离方式有两种:
•基于proxy对全局window生成一个代理对象
•通过快照沙箱在沙箱挂载和卸载的时候记录快照,在应用切换的时候依据快照恢复环境。
5、样式隔离
qiankun内置了两种样式隔离的方法:
•ShadowDOM
•样式隔离 RFC
6、应用间通信
基于一个全局的globalState对象。这个对象由基座应用负责创建,内部包含一组用于通信的变量,以及两个分别用于修改变量值和监听变量变化的方法:setGlobalState和onGlobalStateChange。
总结
虽然阿里说:“可能是你见过最完善的微前端解决方案🧐”。但是qiankun 也有一些事情没有做的。比如没有对 localStorage 进行隔离,如果多个子应用都用到 localStorage 就有可能冲突了,本人已封装好插件解决了此问题,如若需要,留言分享给你。除此之外,还有 cookie, indexedDB 的共享等。