详细解析微前端、微前端框架qiankun以及源码
作者 | 晒兜斯
本⽂将针对微前端框架 qiankun 的源码进⾏深⼊解析,在源码讲解之前,我们先来了解⼀下什么是 微前端。
微前端 是⼀种类似于微服务的架构,它将微服务的理念应⽤于浏览器端,即将单页⾯前端应⽤由单⼀的单体应⽤转变为多个⼩型前端应⽤聚合为⼀的应⽤。各个前端应⽤还可以独⽴开发、独⽴部署。同时,它们也可以在共享组件的同时进⾏并⾏开发——这些组件可以通
过 NPM 或者 Git Tag、Git Submodule 来管理。
qiankun(乾坤) 就是⼀款由蚂蚁⾦服推出的⽐较成熟的微前端框架,基于 single-spa 进⾏⼆次开发,⽤于将 Web 应⽤由单⼀的单体应⽤转变为多个⼩型前端应⽤聚合为⼀的应⽤。(见下图)
那么,话不多说,我们的源码解析正式开始。
初始化全局配置 - start(opts)
我们从两个基础 API - registerMicroApps(apps, lifeCycles?) - 注册⼦应⽤ 和 start(opts?) - 启动主应⽤ 开始,由于 registerMicroApps 函数中设置的回调函数较多,并且读取了 start 函数中设置的初始配置项,所以我们从 start 函数开始解析。
我们从 start 函数开始解析(见下图):
我们对 start 函数进⾏逐⾏解析:
第 196 ⾏:设置 window 的 __POWERED_BY_QIANKUN__ 属性为 true,在⼦应⽤中使
⽤ window.__POWERED_BY_QIANKUN__ 值判断是否运⾏在主应⽤容器中。
第 198~199 ⾏:设置配置参数(有默认值),将配置参数存储在 importLoaderConfiguration 对象中;
第 201~203 ⾏:检查 prefetch 属性,如果需要预加载,则添加全局事件 single-spa:first-mount 监听,在第⼀个⼦应⽤挂载后预加载其他⼦应⽤资源,优化后续其他⼦应⽤的加载速度。
第 205 ⾏:根据 singularMode 参数设置是否为单实例模式。
第 209~217 ⾏:根据 jsSandbox 参数设置是否启⽤沙箱运⾏环境,旧版本需要关闭该选项以兼容 IE。(新版本在单实例模式下默认⽀持 IE,多实例模式依然不⽀持 IE)。
第 222 ⾏:调⽤了 single-spa 的 startSingleSpa ⽅法启动应⽤,这个在 single-spa 篇我们会单独剖析,这⾥可以简单理解为启动主应⽤。
从上⾯可以看出,start 函数负责初始化⼀些全局设置,然后启动应⽤。这些初始化的配置参数有⼀部分将在 registerMicroApps 注册⼦应⽤的回调函数中使⽤,我们继续往下看。
注册⼦应⽤ - registerMicroApps(apps, lifeCycles?)
registerMicroApps 函数的作⽤是注册⼦应⽤,并且在⼦应⽤激活时,创建运⾏沙箱,在不同阶段调⽤不同的⽣命周期钩⼦函数。(见下图)
从上⾯可以看出,在 第 70~71 ⾏ 处 registerMicroApps 函数做了个处理,防⽌重复注册相同的⼦应⽤。
在 第 74 ⾏ 调⽤了 single-spa 的 registerApplication ⽅法注册了⼦应⽤。
我们直接来看 registerApplication ⽅法,registerApplication ⽅法是 single-spa 中注册⼦应⽤的核⼼函数。该函数有四个参数,分别是
name(⼦应⽤的名称)
回调函数(activeRule 激活时调⽤)
activeRule(⼦应⽤的激活规则)
props(主应⽤需要传递给⼦应⽤的数据)
这些参数都是由 single-spa 直接实现,这⾥可以先简单理解为注册⼦应⽤(这个我们会在 single-spa 篇展开说)。在符合 activeRule 激活规则时将会激活⼦应⽤,执⾏回调函数,返回⼀些⽣命周期钩⼦函数(见下图)。
注意,这些⽣命周期钩⼦函数属于 single-spa,由 single-spa 决定在何时调⽤,这⾥我们从函数名来简单理解。(bootstrap - 初始化⼦应⽤,mount - 挂载⼦应⽤,unmount - 卸载⼦应⽤)
如果你还是觉得有点懵,没关系,我们通过⼀张图来帮助理解。(见下图)
获取⼦应⽤资源 - import-html-entry
我们从上⾯分析可以看出,qiankun 的 registerMicroApps ⽅法中第⼀个⼊参 apps - Array<RegistrableApp<T>> 有三个参数 name、activeRule、props 都是交给 single-spa 使⽤,还有 entry 和 render 参数还没有⽤到。
我们这⾥需要关注 entry(⼦应⽤的 entry 地址) 和 render(⼦应⽤被激活时触发的渲染规则) 这两个还没有⽤到的参数,这两个参数延迟到 single-spa ⼦应⽤激活后的回调函数中执⾏。
那我们假设此时我们的⼦应⽤已激活,我们来看看这⾥做了什么。(见下图)
从上图可以看出,在⼦应⽤激活后,⾸先在 第 81~84 ⾏ 处使⽤了 import-html-entry 库从 entry 进⼊加载⼦应⽤,加载完成后将返回⼀个对象(见下图)
我们来解释⼀下这⼏个字段
我们先将 template 模板、getExternalScripts 和 getExternalStyleSheets 函数的执⾏结果打印出来,效果如下(见下图):
从上图我们可以看到我们外部引⼊的三个 js 脚本⽂件,这个模板⽂件没有外部 css 样式表,对应的样式表数组也为空。
然后我们再来分析 execScripts ⽅法,该⽅法的作⽤就是指定⼀个 proxy(默认是 window)对象,然后执⾏该模板⽂件中所有的 JS,并返回 JS 执⾏后 proxy 对象的最后⼀个属性(见下图 1)。在微前端架构中,这个对象⼀般会包含⼀些⼦应⽤的⽣命周期钩⼦函数(见下图2),主应⽤可以通过在特定阶段调⽤这些⽣命周期钩⼦函数,进⾏挂载和销毁⼦应⽤的操作。
好用的前端框架在 qiankun 的 importEntry 函数中还传⼊了配置项 getTemplate,这个其实是对 html ⽬标⽂件的⼆次处理,这⾥就不作展开了,有兴趣的可以⾃⾏去了解⼀下。
主应⽤挂载⼦应⽤ HTML 模板
我们回到 qiankun 源码部分继续看(见下图)
从上图看出,在 第 85~87 ⾏ 处,先对单实例进⾏检测。在单实例模式下,新的⼦应⽤挂载⾏为会在旧的⼦应⽤卸载之后才开始。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论