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

目录
  • 一、多页签是什么?
    • 1.1 单页面应用实现多页签
    • 1.2 使用qiankun进行微前端改造后,多页签缓存有什么不同
  • 二、方案选择
    • 2.1 方案一:多个子应用同时存在
    • 2.2 方案二:同一时间仅加载一个子应用,同时保存其他应用的状态
    • 2.3 最终选择
  • 三、具体实现
    • 3.1 从组件级别的缓存到应用级别的缓存
    • 3.2 移花接木——将vnode重新挂载到一个新实例上
    • 3.3 解决应用级缓存方案的问题
      • 3.3.1 vue-router相关问题
      • 3.3.2 父子组件通信
    • 3.3.3 缓存管理,防止内存泄露
    • 3.4 整体框架
  • 四、现有问题
    • 4.1 暂时只支持vue框架的实例缓存
  • 五、总结

本文梳理了基于阿里开源微前端框架qiankun,实现多页签及子应用缓存的方案,同时还类比了多个不同方案之间的区别及优劣势,为使用微前端进行多页签开发的同学,提供一些参考。

本文梳理了基于阿里开源微前端框架qiankun,实现多页签及子应用缓存的方案,同时还类比了多个不同方案之间的区别及优劣势,为使用微前端进行多页签开发的同学,提供一些参考。

一、多页签是什么?

我们常见的浏览器多页签、编辑器多页签,从产品角度来说,就是为了能够实现用户访问可记录,快速定位工作区等作用;那对于单页应用,可以通过实现多页签,对用户的访问记录进行缓存,从而提供更好的用户体验。

前端可以通过多种方式实现多页签,常见的方案有两种:

  1. 通过CSS样式display:none来控制页面的显示隐藏模块的内容;
  2. 将模块序列化缓存,通过缓存的内容进行渲染(与vue的keep-alive原理类似,在单页面应用中应用广泛)。

相对于第一种方式,第二种方式将DOM格式存储在序列化的JS对象当中,只渲染需要展示的DOM元素,减少了DOM节点数,提升了渲染的性能,是当前主流的实现多页签的方式。

那么相对于传统的单页面应用,通过微前端qiankun进行改造后的前端应用,在多页签上实现会有什么不同呢?

1.1 单页面应用实现多页签

改造前的单页面应用技术栈是Vue全家桶(vue2.6.10 + element2.15.1 + webpack4.0.0+vue-cli4.2.0)。

vue框架提供了keep-alive来支持缓存相关的需求,使用keep-alive即可实现多页签的基本功能,但是为了支持更多的功能,我们在其基础上重新封装了vue-keep-alive组件。

相对较于keep-alive通过include、exclude对缓存进行控制,vue-keep-alive使用更原生的发布订阅方式来删除缓存,可以实现更完整的多页签功能,例如同个路由可以根据参数的不同派生出多个路由实例(如打开多个详情页页签)以及动态删除缓存实例等功能。

下面是vue-keep-alive自定义的拓展实现:

created() {
  // 动态删除缓存实例监听
  this.cache = Object.create(null);
  breadCompBus.$on('removeTabByKey', this.removeCacheByKey);
  breadCompBus.$on('removeTabByKeys', (data) => {
    data.forEach((item) => {
      this.removeCacheByKey(item);
    });
  });
}

vue-keep-alive组件即可传入自定义方法,用于自定义vnode.key,支持同一匹配路由中派生多个实例。

// 传入`vue-keep-alive`的自定义方法
function updateComponentsKey(key, name, vnode) {
  const match = this.$route.matched[1];

  if (match && match.meta.multiNodeKey) {
    vnode.key = match.meta.multiNodeKey(key, this.$route);
    return vnode.key;
  }

  return key;
}

1.2 使用qiankun进行微前端改造后,多页签缓存有什么不同

qiankun是由蚂蚁金服推出的基于Single-Spa实现的前端微服务框架,本质上还是路由分发式的服务框架,不同于原本 Single-Spa采用JS Entry用的方案,qiankun采用HTML Entry 方式进行了替代优化。

使用qiankun进行微前端改造后,页面被拆分为一个基座应用和多个子应用,每个子应用都运行在独立的沙箱环境中。

相对于单页面应用中通过keep-alive管控组件实例的方式,拆分后的各个子应用的keep-alive并不能管控到其他子应用的实例,我们需要缓存对所有的应用生效,那么只能将缓存放到基座应用中。

这个就存在几个问题:

  • 加载:主应用需要在什么时候,用什么方式来加载子应用实例?
  • 渲染:通过缓存实例来渲染子应用时,是通过DOM显隐方式渲染子应用还是有其他方式?
  • 通信:关闭页签时,如何判断是否完全卸载子应用,主应用应该使用什么通信方式告诉子应用?

二、方案选择

通过在Github issues及掘金等平台的一系列资料查找和对比后,关于如何在qiankun框架下实现多页签,在不修改qiankun源码的前提下,主要有两种实现的思路。

2.1 方案一:多个子应用同时存在

实现思路:

在dom上通过v-show控制显示哪一个子应用,及display:none;控制不同子应用dom的显示隐藏。

url变化时,通过loadMicroApp手动控制加载哪个子应用,在页签关闭时,手动调用unmount方法卸载子应用。

示例:

<template>
  <div id="app">
  <header>
    <router-link to="/app-vue-hash/">app-vue-hash</router-link>
    <router-link to="/app-vue-history/">app-vue-history</router-link>
    <router-link to="/about">about</router-link>
  </header>
  <div id="appContainer1" v-show="$route.path.startsWith('/app-vue-hash/')"></div>
  <div id="appContainer2" v-show="$route.path.startsWith('/app-vue-history/')"></div>
  <router-view></router-view>
</div>
</template>
<script>
import { loadMicroApp } from 'qiankun';
const apps = [
{
  name: 'app-vue-hash',
  entry: 'http://localhost:1111',
  container: '#appContainer1',
  props: { data : { store, router } }
},
{
  name: 'app-vue-history',
  entry: 'http://localhost:2222',
  container: '#appContainer2',
  props: { data : store }
}
]
export default {
  mounted() {
    // 优先加载当前的子项目
    const path = this.$route.path;
    const currentAppIndex = apps.findIndex(item => path.includes(item.name));
    if(currentAppIndex !== -1){
      const currApp = apps.splice(currentAppIndex, 1)[0];
      apps.unshift(currApp);
    }
    // loadMicroApp 返回值是 app 的生命周期函数数组
    const loadApps = apps.map(item => loadMicroApp(item))
    // 当 tab 页关闭时,调用 loadApps 中 app 的 unmount 函数即可
  },
}
</script>

具体的DOM展示(通过display:none;控制不同子应用DOM的显隐):

方案优势:

  1. loadMicroApp是qiankun提供的API,可以方便快速接入;
  2. 该方式不卸载子应用,页签切换速度比较快。

方案不足:

  • 子应用切换时不销毁DOM,会导致DOM节点和事件监听过多,严重时会造成页面卡顿;
  • 子应用切换时未卸载,路由事件监听也未卸载,需要对路由变化的监听做特殊的处理。

2.2 方案二:同一时间仅加载一个子应用,同时保存其他应用的状态

实现思路:

  • 通过registerMicroApps注册子应用,qiankun会通过自动加载匹配的子应用;
  • 参考keep-alive实现方式,每个子应用都缓存自己实例的vnode,下次进入子应用时可以直接使用缓存的vnode直接渲染为真实DOM。

方案优势:

  • 同一时间,只是展示一个子应用的active页面,可减少DOM节点数;
  • 非active子应用卸载时同时会卸载DOM及不需要的事件监听,可释放一定内存。

方案不足:

  • 没有现有的API可以快速实现,需要自己管理子应用缓存,实现较为复杂;
  • DOM渲染多了一个从虚拟DOM转化为真实DOM的一个过程,渲染时间会比第一种方案稍多。

vue组件实例化过程简介

这里简单的回顾下vue的几个关键的渲染节点:

vue关键渲染节点(来源:掘金社区)

  • compile:对template进行编译,将AST转化后生成render function;
  • render:生成VNODE虚拟DOM;
  • patch :将虚拟DOM转换为真实DOM;

因此,方案二相对于方案一,就是多了最后patch的过程。

2.3 最终选择

根据两种方案优势与不足的评估,同时根据我们项目的具体情况,最终选择了方案二进行实现,具体原因如下:

  • 过多的DOM及事件监听,会造成不必要的内存浪费,同时我们的项目主要以编辑器展示和数据展示为主,单个页签内内容较多,会更倾向于关注内存使用情况;
  • 方案二在子应用二次渲染时多了一个patch过程,渲染速度不会慢多少,在可接受范围内。

三、具体实现

在上面一部分我们简单的描述了方案二的一个实现思路,其核心思想就是是通过缓存子应用实例的vnode,那么这一部分,就来看下它的一个具体的实现的过程。

3.1 从组件级别的缓存到应用级别的缓存

在vue中,keep-alive组件通过缓存vnode的方式,实现了组件级别的缓存,对于通过vue框架实现的子应用来说,它其实也是一个vue实例,那么我们同样也可以做到通过缓存vnode的方式,实现应用级别的缓存。

通过分析keep-alive源码,我们了解到keep-alive是通过在render中进行缓存命中,返回对应组件的vnode,并在mounted和updated两个生命周期钩子中加入对子组件vnode的缓存。

// keep-alive核心代码
render () {
  const slot = this.$slots.default
  const vnode: VNode = getFirstComponentChild(slot)
  const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
  if (componentOptions) {
    // 更多代码...
    // 缓存命中
    if (cache[key]) {
      vnode.componentInstance = cache[key].componentInstance
      // make current key freshest
      remove(keys, key)
      keys.push(key)
    } else {
      // delay setting the cache until update
      this.vnodeToCache = vnode
      this.keyToCache = key
    }
    // 设置keep-alive,防止再次触发created等生命周期
    vnode.data.keepAlive = true
  }
  return vnode || (slot && slot[0])
}
// mounted和updated时缓存当前组件的vnode
mounted() {
  this.cacheVNode()
}
updated() {
  this.cacheVNode()
}

相对于keep-alive需要在mounted和updated两个生命周期中对vnode缓存进行更新,在应用级的缓存中,我们只需要在子应用卸载时,主动对整个实例的vnode进行缓存即可。

// 父应用提供unmountCache方法
function unmountCache() {
  // 此处永远只会保存首次加载生成的实例
  const needCached = this.instance?.cachedInstance || this.instance;
  const cachedInstance = {};
  cachedInstance._vnode = needCached._vnode;
  // keepalive设置为必须 防止进入时再次created,同keep-alive实现
  if (!cachedInstance._vnode.data.keepAlive) cachedInstance._vnode.data.keepAlive = true;
  // 省略其他代码...

  // loadedApplicationMap用于是key-value形式,用于保存当前应用的实例
  loadedApplicationMap[this.cacheKey] = cachedInstance;
  // 省略其他代码...

  // 卸载实例
  this.instance.$destroy();
  // 设置为null后可进行垃圾回收
  this.instance = null;
}

// 子应用在qiankun框架提供的卸载方法中,调用unmountCache
export async function unmount() {
  console.log('[vue] system app unmount');
  mainService.unmountCache();
}

3.2 移花接木——将vnode重新挂载到一个新实例上

将vnode缓存到内存中后,再将原有的instance卸载,重新进入子应用时,就可以使用缓存的vnode进行render渲染。

// 创建子应用实例,有缓存的vnode则使用缓存的vnode
function newVueInstance(cachedNode) {
  const config = {
    router: this.router,
    store: this.store,
    render: cachedNode ? () => cachedNode : instance.render, // 优先使用缓存vnode
  });
  return new Vue(config);
}
// 实例化子应用实例,根据是否有缓存vnode确定是否传入cachedNode
this.instance = newVueInstance(cachedNode);
this.instance.$mount('#app');

那么,这里不禁就会有些疑问:

  • 如果我们每次进入子应用时,都重新创建一个实例,那么为什么还要卸载,直接不卸载就可以了吗?
  • 将缓存vnode使用到一个新的实例上,不会有什么问题吗?

首先我们回答一下第一个问题,为什么在切换子应用时,要卸载掉原来的子应用实例,有两个考虑方面:

  • 其一,是对内存的考量,我们需要的其实仅仅是vnode,而不是整个实例,缓存整个实例是方案一的实现方案,所以,我们仅需要缓存我们需要的对象即可;
  • 其二,卸载子应用实例可以移除不必要的事件监听,比如vue-router对popstate事件就进行了监听,我们在其他子应用操作时,并不希望原来的子应用也对这些事件进行响应,那么在子应用卸载时,就可以移除掉这些监听。

对于第二个问题,情况会更加复杂一点,下面一个部分,就主要来看下主要遇到了哪些问题,又该如何去解决。

3.3 解决应用级缓存方案的问题

3.3.1 vue-router相关问题

  • 在实例卸载后对路由变化监听失效;
  • 新的vue-router对原有的router params等参数记录失效。

首先我们需要明确这两个问题的原因:

  • 第一个是因为在子应用卸载时移除了对popstate事件的监听,那么我们需要做的就是重新注册对popstate事件的监听,这里可以通过重新实例化一个vue-router解决;
  • 第二问题是因为通过重新实例化vue-router解决第一个问题之后,实际上是一个新的vue-router,我们需要做的就是不仅要缓存vnode,还需要缓存router相关的信息。

大致的解决实现如下:

// 实例化子应用vue-router
function initRouter() {
  const { router: originRouter } = this.baseConfig;
  const config = Object.assign(originRouter, {
    base: `app-kafka/`,
  });
  Vue.use(VueRouter);
  this.router = new VueRouter(config);
}

// 创建子应用实例,有缓存的vnode则使用缓存的vnode
function newVueInstance(cachedNode) {
  const config = {
    router: this.router, // 在vue init过程中,会重新调用vue-router的init方法,重新启动对popstate事件监听
    store: this.store,
    render: cachedNode ? () => cachedNode : instance.render, // 优先使用缓存vnode
  });
  return new Vue(config);
}

function render() {
  if(isCache) {
    // 场景一、重新进入应用(有缓存)
    const cachedInstance = loadedApplicationMap[this.cacheKey];

    // router使用缓存命中
    this.router = cachedInstance.$router;
    // 让当前路由在最初的Vue实例上可用
    this.router.apps = cachedInstance.catchRoute.apps;
    // 使用缓存vnode重新实例化子应用
    const cachedNode = cachedInstance._vnode;
    this.instance = this.newVueInstance(cachedNode);
  } else {
    // 场景二、首次加载子应用/重新进入应用(无缓存)
    this.initRouter();
    // 正常实例化
    this.instance = this.newVueInstance();
  }
}

function unmountCache() {
  // 省略其他代码...
  cachedInstance.$router = this.instance.$router;
  cachedInstance.$router.app = null;
  // 省略其他代码...
}

3.3.2 父子组件通信

多页签的方式增加了父子组件通信的频率,qiankun有提供setGlobalState通信方式,但是在单应用模式下,同一时间仅支持和一个子应用进行通行,对于unmount 的子应用来说,无法接收到父应用的通信,因此,对于不同的场景,我们需要更加灵活的通信方式。

子应用——父应用:使用qiankun自带通信方式;

从子到父的通信场景较为简单,一般只有路由变化时进行上报,并且仅为激活状态的子应用才会上报,可直接使用qiankun自带通信方式;

父应用——子应用:使用自定义事件通信;

父应用到子应用,不仅需要和active状态的子应用通信,还需要和当前处于缓存中子应用通信;

因此,父应用到子应用,通过自定义事件的方式,能够实现父应用和多个子应用的通信。

// 自定义事件发布
const evt = new CustomEvent('microServiceEvent', {
  detail: {
    action: { name: action, data },
    basePath, // 用于子应用唯一标识
  },
});
document.dispatchEvent(evt);

// 自定义事件监听
document.addEventListener('microServiceEvent', this.listener);

3.3.3 缓存管理,防止内存泄露

  • 使用缓存最重要的事项就是对缓存的管理,在不需要的时候及时清理,这在JS中是非常重要但很容易被忽略的事项。

应用级缓存

  • 子应用vnode、router等属性,子应用切换时缓存;

页面级缓存

  • 通过vue-keep-alive缓存组件的vnode;
  • 删除页签时,监听remove事件,删除页面对应的vnode;
  • vue-keep-alive组件中所有缓存均被删除时,通知删除整个子应用缓存;

3.4 整体框架

最后,我们从整体的视角来了解下多页签缓存的实现方案。

因为不仅仅需要对子应用的缓存进行管理,还需要将vue-keep-alive组件注册到各个子应用中等事项,我们将这些服务统一在主应用的mainService中进行管理,在registerMicroApps注册子应用时通过props传入子应用,这样就能够实现同一套代码,多处复用。

// 子应用main.js
let mainService = null;

export async function mount(props) {
  mainService = null;
  const { MainService } = props;
  // 注册主应用服务
  mainService = new MainService({
  // 传入对应参数
  });
  // 实例化vue并渲染
  mainService.render(props);
}
export async function unmount() {
  mainService.unmountCache();
}

最后对关键流程进行梳理:

四、现有问题

4.1 暂时只支持vue框架的实例缓存

该方案也是基于vue现有特性支持实现的,在react社区中对于多页签实现并没有统一的实现方案,笔者也没有过多的探索,考虑到现有项目是以vue技术栈为主,后期升级也会只升级到vue3.0,在一段时间内是可以完全支持的。

五、总结

相较于社区上大部分通过方案一进行实现,本文提供了另一种实现多页签缓存的一种思路,主要是对子应用缓存处理上有些许的不同,大致的思路及通信的方式都是互通的。

另外本文对qiankun框架的使用没有做太多的发散总结,官网和Github上已经有很多相关问题的总结和踩坑经验可供参考。

最后,如果文章有什么问题或错误,欢迎指出,谢谢。

参考阅读

qiankun 微前端实践总结(二)

[Feature Request] 主应用多页签切换不同子应用的页面状态保持 #361

基于qiankun的微前端多页签项目实践与总结

到此这篇关于基于微前端qiankun的多页签缓存方案实践的文章就介绍到这了,更多相关微前端qiankun多页签缓存内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解ant-design-pro使用qiankun微服务

    目录 主应用配置 子应用配置 微服务现在挺火的,优点也很明显如果有多个应用都有相同页面时,就可以使用微服务,可以避免重复写代码 在网上搜了下,很多例子都是基于官方文档的例子,官方文档:https://umijs.org/zh-CN/plugins/plugin-qiankun.比较简单,实际使用场景会有特殊情况我根据自己项目的情况总结了一下使用方法 我们两个项目都是ant-design-pro的,我这里的例子也用的ant-design-pro项目生成的, githup地址:https://git

  • 微前端qiankun改造日渐庞大的项目教程

    项目背景 很多小伙伴在工作中都碰到过和我一样的场景,手上的某个项目越来越大,眼看着每次build时间越来越长,吐了.在杭州某独角兽我碰到了这样的一个项目,他叫运营后台,听名字就知道,他的主要用户是运营人员.问题就是随着公司业务的越来越多,这个运营后台承担的已经不是某一块业务了,而是所有业务的运营操作的中后台都在这上面.你可以这样理解,这个系统的每个一级菜单都是一块独立的业务,相互之间没有任何瓜葛:按常规的理解,这应该是单独的每一个project比较合理,但是正因为他的用户又都是公司的同一群人,他

  • ant-design-pro使用qiankun微服务配置动态主题色的问题

    使用微服务后,遇到一个问题,主应用和子应用的主题色不一致.希望可以通过主应用的颜色动态变换子应用的主题色ant-design-pro可以通过config.ts配置全局主题色所有最优的方法是可以通过改变主题色,来动态配置.官方最新版本的https://github.com/ant-design/ant-design-pro/releases/tag/v5.2.0已经支持了,通过<SettingDrawer>设置之前的版本不支持直接修改主题色.但是ant-design支持全局修改组件颜色跟着官方的

  • 微前端qiankun沙箱实现源码解读

    目录 前言 LegacySandbox单实例沙箱 ProxySandbox多实例沙箱 SapshotSandbox 快照沙箱 结束语 前言 上篇我们介绍了微前端实现沙箱的几种方式,没看过的可以下看下JS沙箱这篇内容,扫盲一下.接下来我们通过源 码详细分析下qiankun沙箱实现,我们clone下qiankun代码,代码主要在sandbox文件夹下,目录结构为 ├── common.ts ├── index.ts // 入口文件 ├── legacy │ └── sandbox.ts // 代理沙

  • qiankun 找不到入口问题彻底解决

    目录 前言 为什么要找生命周期 如何找入口 兜底找入口 微应用的 Webpack 配置 主应用的兜底逻辑 总结 前言 嗨害嗨,好久不见,我是海怪. 有一阵子没写文章了,今天来更一期关于 qiankun 找不到生命周期的问题. 刚开始给项目接入 qiankun 的时候,时不时就会报 Application died in status LOADING_SOURCE_CODE: You need to export the functional lifecycles in xxx entry: 开发

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

    目录 一.多页签是什么? 1.1 单页面应用实现多页签 1.2 使用qiankun进行微前端改造后,多页签缓存有什么不同 二.方案选择 2.1 方案一:多个子应用同时存在 2.2 方案二:同一时间仅加载一个子应用,同时保存其他应用的状态 2.3 最终选择 三.具体实现 3.1 从组件级别的缓存到应用级别的缓存 3.2 移花接木——将vnode重新挂载到一个新实例上 3.3 解决应用级缓存方案的问题 3.3.1 vue-router相关问题 3.3.2 父子组件通信 3.3.3 缓存管理,防止内存

  • Vue qiankun微前端实现详解

    目录 引言 What:微前端是什么 Why:为什么选择微前端 微前端能做到什么 为什么不使用iFrame How:微前端实践 在主应用中注册微应用 在子应用导出相应的生命周期钩子 结尾 引言 前端时间有个契机,让我们团队开始进行微前端的相关实践. 最近正好有些成果了,来一个阶段性的总结,也方便后续进一步的开发. 可能第一次听说微前端的同学都会不明觉厉,那么ta到底是个啥?本章会从以下3个角度阐述我的理解: What:微前端是什么 Why:为什么选择微前端 How:微前端实践 What:微前端是什

  • 微前端框架qiankun源码剖析之下篇

    目录 引言 四.沙箱隔离 4.1 JS隔离 1. Snapshot沙箱 2. Legacy沙箱 3. Proxy沙箱 4.2 CSS隔离 1. ShadowDOM 2. Scoped CSS 五.通信方式 六.结语 引言 承接上文  微前端框架qiankun源码剖析之上篇 注意: 受篇幅限制,本文中所粘贴的代码都是经过作者删减梳理后的,只为讲述qiankun框架原理而展示,并非完整源码.如果需要阅读相关源码可以自行打开文中链接. 四.沙箱隔离 在基于single-spa开发的微前端应用中,子应用

  • 基于Vue实现微前端的示例代码

       前端微服务化一直是前端社区的一个热门话题,早在2018年就有不少开发者提出过各种解决方案.或许是未得精髓,个人认为基于Web Components的实现脱离整体打包逻辑的,难以工程化.直到遇到了vue-cli 3,子模块打包的问题得以迎刃而解.2019年秋,团队内部初步实现前端分布式开发,解决了集中式开发部署的"老大难"问题.个人认为,随着WebAssembly等技术的兴起,"前端后移"越来越明显,前端微服务会成为大前端的一个趋势.下面简单分享下本人对前端微服

  • 基于Vue CSR的微前端实现方案实践

    在这里就不讲微前端的各种优缺点,直接假设你在负责一个中后台管理系统的开发,所有的业务模块全部都在一个项目中打包,随着业务量的不断增长,编译越来越慢,你期望可以从老的项目中将新的业务进行独立开发.独立部署,以微应用的形式嵌入到老项目中. 本篇文章的受众是那些希望在新老的项目中,在不需要你对老项目进行改动老项目的前提下,嵌入微应用,如果本篇文章对你有帮助,请点个:+1:! 核心要素 构建生产环境代码,输出远程组件所需的 JSON 通过 ajax 请求,拿到这个 JSON 的数据,传给 远程组件 新项

  • vite构建项目并支持微前端

    目录 基础配置 支持微前端构建 其他说明 1. 老旧浏览器的支持 2. 关于 TypeScript 的说明 3. 对接 CDN 4. 构建出错 4.1 找不到包 4.2 请求超时 4.3 导入模块出错 小结 得益于 esbuild 的超高性能,vite 在诞生之初就备受关注,且一直保持着活跃的开发迭代.截至目前,vite 已经迭代到了 2.7.10 版本,各方面也基本具备了在生产使用的条件.这段时间,我在项目中尝试了使用 vite 进行打包构建,本文就是这次构建的过程记录. 基础配置 首先使用v

  • JS微前端MicroApp基础使用

    目录 1. 介绍 2. 主应用 2.1 路由配置和基础页面 2.2 全局生命周期配置 2.3 主应用插件系统 3. 子应用 3.1 Webpack + Vue 子应用 3.2 Webpack + React 子应用 4. 应用路由配置说明 4.1 主应用路由 4.2 子应用路由 1. 介绍 MicroApp 是“京东零售”团队在2021年7月正式发布的一个微前端框架,并且抛弃了 Single SPA 的实现理念,基于 CustomElement 和 ShadowDom 来实现. MicroAPP

  • 详解无界微前端是如何渲染子应用的demo解析

    目录 正文 无界渲染子应用的步骤 创建子应用 iframe 解析入口 HTML 处理 CSS 并重新嵌入 HTML 创建 webComponent 并挂载 HTML JS 的执行细节 简单的实现 将 UI 渲染到 shadowRoot 挟持 document 的属性/方法 副作用的处理 DOM 相关的副作用处理 修正相对 URl 修正 shadowRoot head.body iframe 的副作用处理 History API window/document 属性/事件 location 对象

随机推荐