微前端 无界基本用法

250 阅读5分钟

微前端 无界基本用法

目录

[TOC]

无界方案​

在乾坤的 issue 中一个 议题 非常有意思,有个开发者提出能否利用 iframe 来实现 js 沙箱能力,这个 idea 启发了无界方案,下面详细介绍

应用加载机制和 js 沙箱机制​

将子应用的 js 注入主应用同域的 iframe 中运行, iframe 是一个原生的 window 沙箱,内部有完整的 historylocation 接口,子应用实例 instance 运行在 iframe 中,路由也彻底和主应用解耦,可以直接在业务组件里面启动应用。

采用这种方式我们可以获得

收益

  • 组件方式来使用微前端

不用注册,不用改造路由,直接使用无界组件,化繁为简

  • 一个页面可以同时激活多个子应用

子应用采用iframe的路由,不用关心路由占用的问题

  • 天然 js 沙箱,不会污染主应用环境

不用修改主应用 window 任何属性,只在 iframe 内部进行修改

  • 应用切换没有清理成本

由于不污染主应用,子应用销毁也无需做任何清理工作

路由同步机制​

iframe 内部进行 history.pushState ,浏览器会自动的在 joint session history 中添加 iframesession-history ,浏览器的前进、后退在不做任何处理的情况就可以直接作用于子应用

劫持 iframehistory.pushStatehistory.replaceState ,就可以将子应用的 url 同步到主应用的 query 参数上,当刷新浏览器初始化 iframe 时,读回子应用的 url 并使用 iframehistory.replaceState 进行同步

采用这种方式我们可以获得

收益

  • 浏览器刷新、前进、后退都可以作用到子应用
  • 实现成本低,无需复杂的监听来处理同步问题
  • 多应用同时激活时也能保持路由同步

iframe 连接机制和 css 沙箱机制​

无界采用 webcomponent 来实现页面的样式隔离,无界会创建一个 wujie 自定义元素,然后将子应用的完整结构渲染在内部

子应用的实例 instanceiframe 内运行, dom 在主应用容器下的 webcomponent 内,通过代理 iframedocumentwebcomponent ,可以实现两者的互联。

document 的查询类接口: getElementsByTagName、getElementsByClassName、getElementsByName、getElementById、querySelector、querySelectorAll、head、body 全部代理到 webcomponent ,这样 instancewebcomponent 就精准的链接起来。

当子应用发生切换, iframe 保留下来,子应用的容器可能销毁,但 webcomponent 依然可以选择保留,这样等应用切换回来将 webcomponent 再挂载回容器上,子应用可以获得类似 vuekeep-alive 的能力.

采用这种方式我们可以获得

收益

  • 天然 css 沙箱

直接物理隔离,样式隔离子应用不用做任何修改

  • 天然适配弹窗问题

document.bodyappendChild 或者 insertBefore 会代理直接插入到 webcomponent ,子应用不用做任何改造

  • 子应用保活

子应用保留 iframewebcomponent ,应用内部的 state 不会丢失

  • 完整的 DOM 结构

webcomponent 保留了子应用完整的 html 结构,样式和结构完全对应,子应用不用做任何修改

通信机制​

承载子应用的 iframe 和主应用是同域的,所以主、子应用天然就可以很好的进行通信,在无界我们提供三种通信方式

  • props 注入机制

子应用通过 $wujie.props 可以轻松拿到主应用注入的数据

  • window.parent 通信机制

子应用 iframe 沙箱和主应用同源,子应用可以直接通过 window.parent 和主应用通信

  • 去中心化的通信机制

无界提供了 EventBus 实例,注入到主应用和子应用,所有的应用可以去中心化的进行通信

优势​

通过上面原理的阐述,我们可以得出无界微前端框架的几点优势:

优势

  • 多应用同时激活在线

框架具备同时激活多应用,并保持这些应用路由同步的能力

  • 组件式的使用方式

无需注册,更无需路由适配,在组件内使用,跟随组件装载、卸载

  • 应用级别的 keep-alive

子应用开启 保活模式 后,应用发生切换时整个子应用的状态可以保存下来不丢失,结合 预执行模式 可以获得类似 ssr 的打开体验

  • 纯净无污染

  • 无界利用 iframewebcomponent 来搭建天然的 js 隔离沙箱和 css 隔离沙箱

  • 利用 iframehistory 和主应用的 history 在同一个 top-level browsing context 来搭建天然的路由同步机制

  • 副作用局限在沙箱内部,子应用切换无需任何清理工作,没有额外的切换成本

  • 性能和体积兼具

  • 子应用执行性能和原生一致,子应用实例 instance 运行在 iframewindow 上下文中,避免 with(proxyWindow){code} 这样指定代码执行上下文导致的性能下降,但是多了实例化 iframe 的一次性的开销,可以通过 preload 提前实例化

  • 体积比较轻量,借助 iframewebcomponent 来实现沙箱,有效的减小了代码量

  • 开箱即用

不管是样式的兼容、路由的处理、弹窗的处理、热更新的加载,子应用完成接入即可开箱即用无需额外处理,应用 接入成本 也极低

无界入门

我们使用Vue3来充当主应用 首先需要安装依赖

pnpm i wujie-vue3  

主应用的main.ts

import { createApp } from "vue";
import App from "./App.vue";
import Wujie from "wujie-vue3"; //引入对应的框架
createApp(App).use(Wujie).mount("#app"); //注册一下

主应用hellowWord url填写子应用的url 子应用通过npm run dev启动

<template>
  <div>
    <h1>主应用</h1>
    <WujieVue
      width="100%"
      height="100%"
      name="react"
      :url="reactUrl"
    ></WujieVue>
    <WujieVue width="100%" height="100%" name="vue" :url="vueUrl"></WujieVue>
  </div>
</template>
 
<script setup lang='ts'>
import { ref, reactive } from "vue";
const reactUrl = "http://127.0.0.1:5174/";
const vueUrl = "http://127.0.0.1:5175/";
</script>
 
<style scoped lang='less'></style>

只需要简单的几行代码就可以实现微前端应用,接入成本很低