关于微前端:微前端框架singlespa子应用加载解析

5次阅读

共计 4919 个字符,预计需要花费 13 分钟才能阅读完成。

作者:京东物流 宁冲

1 前言

什么是微前端?
微前端是指存在于浏览器中的微服务。

本文次要通过对微前端框架 single-spa 的基座利用加载子利用的 single-spa-vue 函数库进行剖析,通过代码维度剖析让大家理解在 single-spa 加载子利用的时候都做了哪些事件。如何通过优化 single-spa-vue 函数库放弃子利用的状态。

因为是在代码维度进行剖析,要求读者对 single-spa 有肯定的理解,浏览成果会更好。

2 single-spa 加载子利用的过程

基座利用中配置的加载子利用配置,在配置子利用对象的 app 办法中会把子利用 chunk-vendors.js、app.js 插入到页面,并且执行 chunk-vendors.js、app.js 两个子利用依赖的 js。

app 办法执行完结当前,子利用依赖的 js 插入页面当前的 dom 构造。

由下面 app 办法的执行过程,咱们能够看出基座利用加载子利用,和 vue 框架打包后加载 js 资源的形式相似。那么为什么只须要加载子利用的 app.js 和 chunk-vendors.js 就能够把子利用渲染到页面下面。上面咱们再来看看子利用的入口文件 main.js 办法中是如何进行配置的。

3 子利用的 main.js 中的配置

在子利用 main.js 中咱们能够看到,把惯例的配置 1 替换为配置 2 的格局。

在配置 2 中咱们会把以后 vue 的配置传给 single-spa-vue 函数库中。包含 el、render 办法、Vue 对象。通过 singleSpaVue 的包装,返回 single-spa 生命周期办法 bootstrap、mount、unmount。

  • bootstrap:疏导函数,利用内容首次挂载到页背后调用,只会执行一次。
  • mount:挂载函数,子利用每次被挂载的时候都会执行。
  • unmount:卸载函数,子利用每次被卸载的时候都会执行。

也就是说基座利用在加载子利用的时候就是通过 single-spa-vue 函数的解决,生成了 single-spa 的各个生命周期,给基座利用在加载子利用的时候调用。
上面咱们来看看 single-spa-vue 到底是如何生成各种生命周期函数的。

4 single-spa-vue 源码构造

single-spa-vue 函数库能够帮忙咱们来生成加载子利用的生命周期。你能够通过上面链接:single-spa-vue GIT 地址,下载 single-spa-vue 函数库的源码。
single-spa-vue 的源码非常简单,只有几个生成 single-spa 生命周期的函数。

  • single-spa-vue 办法:single-spa-vue 函数库对外提供服务的惟一一个办法,用来接管配置项,并且返回一个蕴含各个 single-spa 生命周期的对象。
  • single-spa-vue 中的其余办法 bootstrap、mount、update、unmount 是用来生成 single-spa 对应生命周期函数的办法。

上面咱们具体介绍一下这几个办法的作用和实现。

5 single-spa-vue 源码解析

single-spa-vue 中提供的 singleSpaVue 办法会接管 userOpts 配置信息,配置信息会和默认的配置项 defaultOpts 合并当前再进行进行后续解决。

5.1 配置项 defaultOpts

对于默认的配置项会有上面这几项,这里只介绍一下必填项,appOptions、Vue/createApp。其中的 template 在并没有在 single-spa-vue 中被用到,然而在 single-spa-html 中有应用到。

  1. // 默认配置项列表
  2. const defaultOpts = {
  3. // required opts
  4. appOptions: null,
  5. template: null,
  6. // sometimes require opts
  7. Vue: null,
  8. createApp: null,
  9. handleInstance: null
  10. }

1)appOptions 配置项介绍

  • appOptions:利用的配置项,会在初始化 Vue 实例的时候作为参数传给 Vue 办法,上面具体介绍一下 appOptions 中的配置项。
  • el:子利用须要挂载的基座 dom,即 vue 须要挂载的 dom。
  • render/template:vue 的 render/template 配置项。
  • data:初始化的参数对象,会在执行挂载函数 mount 的时候间接挂载到 vue 实例上。

2)Vue/createApp 配置项介绍

Vue/createApp 配置项是用来生成 vue 实例的,single-spa-vue 函数库能够通过传入的 Vue 对象在 mount 办法中来生成 vue 实例。也能够传入 createApp 办法,由子利用在 createApp 办法中返回 vue 实例。

上面咱们会在生命周期生成办法中看到这些配置项的作用

5.2 入口办法:singleSpaVue

singleSpaVue 办法会对入参先进行下列有效性校验,具体校验的内容有一下四项。

  1. 配置项 userOpts 是否为对象。
  2. 用来创立 vue 实例的配置 Vue/createApp 是否存在。
  3. 用来生成 vue 实例的配置项 appOptions 是否存在。
  4. vue 实例挂载的 dom 是否正确 appOptions.el 有效性校验。

有效性校验通过当前,会调用 bootstrap、mount、unmount、update 办法用来别离生成 single-spa 加载子利用的生命周期函数。
上面具体介绍一下各个生命周期函数是如何生成的。

5.3 疏导函数:bootstrap

疏导函数 bootstrap,当利用内容首次挂载到页背后调用。

bootstrap 函数,会先判断一下是否在配置项中存在 loadRootComponent。配置项 loadRootComponent 笔者了解是能够用来加载以后子利用依赖的父级利用或者其余的依赖资源。
比方 A 页面依赖 B 组件,那在加载 A 页面的时候能够 loadRootComponent 办法中把 B 组件的动态资源加载下来,并且渲染到页面上,A 页面就能够间接应用 B 组件中提供的一些资源或者 dom。
如果未配置 loadRootComponent,则间接返回,不做任何解决。

5.4 子利用挂载生命周期:mount

在子利用每次被挂载到页面上的时候,single-spa 会执行 mount 生命周期函数,single-spa-vue 在 mount 函数中用来初始化子利用的 vue 实例,并且把实例挂载到页面上。
mount 函数会接管三个参数,别离是 singleSpaVue 传入的参数 opts,single-spa-vue 以后全局挂载的子利用实例列表 mountedInstances,在基座利用中注册的以后子利用的 single-spa 实例 props
props 入参接管的数据,这里只用到了 props 的 name 属性,用来标识以后挂载的子利用。

在 mount 办法中次要做了以下几件事

1)格式化利用配置项 appOptions

mount 办法中会通过 resolveAppOptions 办法来格式化利用的配置项 appOptions。
在 resolveAppOptions 办法来中如果 appOptions 是一个办法的话,则执行办法,并且传递基座利用通过 customProps 参数传入的参数 props。
子利用能够在 appOptions 办法中获取父利用传递的参数、依据父利用的状态做不同的解决等。

2)初始化子利用须要挂载的 DOM 对象。

初始化 dom 的配置和办法比拟多,会从很多个配置项中来获取 el,代码比较简单,这里就不赘述了。只列出来取值的优先级供大家参考。
appOptions.el > props.domElement > props.name

dom 节点被格式化实现当前,上面就开始把页面挂载到 dom 下面。

3)创立 vue 示例,并且挂载到页面上

在挂载页面之前会有一个配置项:replaceMode,replaceMode 配置项是用来标识是否须要替换 el 节点下的内容。默认 replaceMode 为 false 是会在 el 节点上面新建一个 class 为 single-spa-container 的空白 div 来保留子利用。

以 demo 中的代码为例:

默认 replaceMode 为 false 的状况下,基座中的的内容和 vue1 中的内容会并存。如下图:

如果把 replaceMode 改为 true 的状况下,会发现基座中的内容会被 vue1 中的内容笼罩掉。
如下图:

设置挂载形式当前,就开始把子利用真正挂载到 dom 下面。
这里反对两种挂载形式,一种是应用 vue3 的 createApp 形式挂载,一种是应用 vue2 的 new Vue 形式进行挂载。这里的挂载形式其实和咱们在应用 vue 挂载到 dom 形式的配置是一样的。

通过下面的步骤,此时子利用就被挂载到了 html 的页面中的 dom 上了。

5.5 更新生命周期函数:update

当调用 parcel.update() 会触发 update 办法,笔者因为并没有用的高级个性 parcel,在此处不再做过多介绍。

5.6 子利用卸载生命周期:unmount

当页面 url 发生变化的时候,来到子利用页面路由的时候会触发 unmount 办法。
在 unmount 办法中次要做的事件有:

  1. 卸载 vue 利用
  2. 删除 vue 实例
  3. 同时清空页面 dom。

执行 unmount 操作当前子利用的数据和 dom 就会被革除洁净。

5.7 小结

以上就是 single-spa 官网提供的 single-spa-vue 函数库来挂载子利用的全副流程。通过下面的剖析,咱们发现 single-spa-vue 函数库会通过调用 singleSpaVue 办法返回一个蕴含 bootstrap、mount、update、unmount 四个办法的对象。在基座利用加载子利用的生命周期会执行对应的办法,通过执行办法把子利用挂载到基座利用或者从基座利用销毁子利用。

通过 single-spa-vue 中加载子利用的过程,single-spa 把各个子利用组装成一个简单的利用,在用户无感的状况下对各个子利用进行别离治理。

single-spa 在加载子利用的时候,除了 vue 的版本之外,还有其余的版本,然而加载的思路相似,都是在函数库中来把子利用加载到 html 中,此处不再介绍其余类型的加载。
single-spa 其余加载子利用形式:single-spa-react、single-spa-html

6 子利用状态放弃

在理论开发的过程中笔者遇到有些页面须要应用 vue 中的 keep-alive 来保留状态,在页面切换的过程中尽管页面被销毁然而页面状态须要在保留,然而咱们在剖析 single-spa-vue 的 unmount 办法实现的时候发现,如果页面切换,子利用和 vue 实例被销毁,此时子利用中的 keep-alive 是没有失效的。

如下图:

当在 input 中输出内容当前,传统的 spa 我的项目能够通过 keep-alive 来记录状态,当页面路由切换当前,再切回来,依然放弃状态。然而如果间接应用 single-spa-vue,当子利用触发 unmount 的时候 input 中的输出内容 1111 会被清空。针对这种状况,笔者对 single-spa-vue 类库进行了一些革新。

革新内容如下:

6.1 子利用由销毁改为暗藏

在 single-spa-vue 配置项中减少了一个配置项,依据配置项中是否存在 isKeepAlive 配置项,来判断把以后的 dom 暗藏掉,还是删除。这样当子利用 unmount 办法触发的时候,子利用并未被删除,而是依然保留。

同时笔者对 vue 的 route 配置也进行了一些优化,当页面不存在的时候,此时会把子利用中的一个空组件挂载到 dom 下面,防止尽管页面被暗藏掉,然而 dom 依然在 html 中,导致页面 dom 过多。

6.2 子利用由新建改为显示

在 single-spa-vue 配置项中调用 mount 办法挂载子利用的时候,会判断以后子利用是否存在,如果子利用存在则间接把子页面显示进去,因为子利用并未被销毁,此时子利用中的 keep-alive 就会始终失效,并且保留页面的状态。

通过对 single-spa-vue 类库的 mount、unmount 办法的优化,用户在应用页面的时候真正和应用 vue 那样晦涩,并且能够放弃页面状态,晋升用户的体验。

正文完
 0