qiankun 子应用keep-alive实现方案

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了qiankun 子应用keep-alive实现方案相关的知识,希望对你有一定的参考价值。

参考技术A 一、核心设计理念

由于主应用微应用都能做到技术栈无关,qiankun 对于用户而言只是一个类似 jQuery 的库,你需要调用几个 qiankun 的 API 即可完成应用的微前端改造。同时由于 qiankun 的 html entry 及沙箱的设计,使得微应用的接入像使用 iframe 一样简单。

微前端的核心目标是将巨石应用拆解成若干可以自治的松耦合微应用,而 qiankun 的诸多设计均是秉持这一原则,如 HTML entry、沙箱、应用间通信等。这样才能确保微应用真正具备 独立开发、独立运行 的能力。

二、快速上手

2.在主应用中注册微应用

当微应用信息注册完之后,一旦浏览器的 url 发生变化,便会自动触发 qiankun 的匹配逻辑,所有 activeRule 规则匹配上的微应用就会被插入到指定的 container 中,同时依次调用微应用暴露出的生命周期钩子。

如果微应用不是直接跟路由关联的时候,你也可以选择手动加载微应用的方式:

3.微应用配置
微应用分为有 webpack 构建和无 webpack 构建项目,有 webpack 的微应用(主要是指 Vue、React、Angular)需要做的事情有:

新增 public-path.js 文件,用于修改运行时的 publicPath。
注意:运行时的 publicPath 和构建时的 publicPath 是不同的,两者不能等价替代。

微应用建议使用 history 模式的路由,需要设置路由 base,值和它的 activeRule 是一样的。
在入口文件最顶部引入 public-path.js,修改并导出三个生命周期函数。
修改 webpack 打包,允许开发环境跨域和 umd 打包。
主要的修改就是以上四个,可能会根据项目的不同情况而改变。例如,你的项目是 index.html 和其他的所有文件分开部署的,说明你们已经将构建时的 publicPath 设置为了完整路径,则不用修改运行时的 publicPath (第一步操作可省)。

无 webpack 构建的微应用直接将 lifecycles 挂载到 window 上即可。

此处以vue为例:

1.在src目录新增 public-path.js:

2.入口文件 main.js 修改,为了避免根 id #app 与其他的 DOM 冲突,需要限制查找范围。

三、qiankun微应用keep-alive实现方案
背景:qiankun提供了两种加载子应用的方式 registerMicroApps和loadMicroApp。官方推荐的是registerMicroApps路由匹配激活子应用,当浏览器 url 发生变化时,会自动检查每一个微应用注册的 activeRule 规则,符合规则的应用将会被自动激活。但是在微应用和主应用之间切换时,每次都会刷新状态,没办法保持上次操作状态。此时就需要用到loadMicroApp来手动加载微应用,这种需要手动去调用加载和卸载方法。

实现方案

到现在加载已经完成了,打开主应用和微应用页面,来回切换已经实现了状态保持,接下来就是卸载微应用。标签被关闭的时候去判断是否需要卸载。

qiankun配置父子应用及挂载问题

这两天研究了下qiankun这个微前端实现,正好写了两个项目用的是umi且是父子应用关系,之前的方式是在主应用添加iframe将子应用引进来,现在想通过改造成qiankun来将两个应用联系起来,顺便试试这个库。

事先说明父应用umi版本为2.9.0,子应用umi版本为2.10.0

具体操作是父子应用均通过yarn add @umijs/plugin-qiankun添加qiankun插件,父应用.umirc.ts添加如下:

const config:IConfig = {
  ...,
  routes: [
    ...,
    {
      path, ‘/app‘ // 这里是子应用的路由
    }
  ],
  plugins: [
    ...,
    [
      ‘@umijs/plugin-qiankun‘,
      {
        master: {
          apps: [
            {
              name: ‘app‘,
              entry: ‘//localhost:9090‘,
              base: ‘/app‘,
              history: ‘browser‘,
              mountElementId: ‘root-slave‘,  // 注意这里是子应用要挂载在父应用上的节点id
            }
          ],
          jsSandBox: true,
          prefetch: true,
        }
      }
    ]
  ],
  proxy: {} // 如果是开发模式记得配置代理调用子应用服务端
}

配置完成后可以来到根组件下例如layout/index.tsx<div>{props.children}<div id=‘root-slave‘></div></div>,其中root-slave的div就是子应用将要挂载的节点,这点很关键,如果没有的话将会提示Uncaught (in promise) Error: Target container is not a DOM element.之类的报错,还有一种方式是新建一个子应用组件,例如pages/subAppContainer.tsx组件,然后:

import React from ‘react‘;
export default () => {
  return (
    <div id=‘root-slave‘></div>
  )
}

这个时候.umirc.ts中routes里面应该添加component

{
  path: ‘/app‘, component: ‘./subAppContainer‘
}

配置app.ts,添加子应用生命周期函数:

export const qiankun = new Promise(resolve => {
  resolve({
    lifeCycles: {
      beforeLoad: props => {
        console.log(‘beforeLoad:‘, props);
      },
      beforeMount: props => {
        console.log(‘beforeMont:‘, props);
      },
      afterMount: props => {
        console.log(‘afterMount:‘, props);
      },
      beforeUnmount: props => {
        console.log(‘beforeUnmount:‘, props);
      },
      afterUnmount: props => {
        console.log(‘afterUmount:‘, props);
      },
    },
  });
});

至此主应用就配置的差不多了,接下来配置子应用

添加pages/document.ejs将根节点id修改为app-slave或者其他啥名字,配置.umirc.js

export default {
  ...,
  plugins: [
    ...,
    [
      ‘@umijs/plugin-qiankun/slave‘,
      {
        // 如果有其他配置请参照https://github.com/umijs/umi-plugin-qiankun里面进行配置
      },
      base: ‘/app‘,
      mountElementId: ‘app-slave‘ // 与`document.ejs`的根节点id保持一致
    ]
  ]
}

此前子应用的服务端前缀为/api,为了避免与主应用冲突,将子应用服务端前缀改为/app/api
如此此次改造基本完成,过程中碰到的最大问题就是子应用的挂载问题,如果碰到其他问题也可以去umi的仓库提issue。


以上是关于qiankun 子应用keep-alive实现方案的主要内容,如果未能解决你的问题,请参考以下文章

基于微前端qiankun的多页签缓存方案实践

微前端——乾坤qiankun Demo

qiankun框架引入子应用element-ui图标不显示

qiankun配置父子应用及挂载问题

qianKun + VUE 实现微前端架构 (基于vue2实现)

微前端qiankun架构 (基于vue2实现)使用教程