微前端 无界基本用法
目录
[TOC]
无界方案
在乾坤的 issue 中一个 议题 非常有意思,有个开发者提出能否利用 iframe 来实现 js 沙箱能力,这个 idea 启发了无界方案,下面详细介绍
应用加载机制和 js 沙箱机制
将子应用的 js 注入主应用同域的 iframe 中运行, iframe 是一个原生的 window 沙箱,内部有完整的 history 和 location 接口,子应用实例 instance 运行在 iframe 中,路由也彻底和主应用解耦,可以直接在业务组件里面启动应用。
采用这种方式我们可以获得
收益
- 组件方式来使用微前端
不用注册,不用改造路由,直接使用无界组件,化繁为简
- 一个页面可以同时激活多个子应用
子应用采用iframe的路由,不用关心路由占用的问题
- 天然 js 沙箱,不会污染主应用环境
不用修改主应用 window 任何属性,只在 iframe 内部进行修改
- 应用切换没有清理成本
由于不污染主应用,子应用销毁也无需做任何清理工作
路由同步机制
在 iframe 内部进行 history.pushState ,浏览器会自动的在 joint session history 中添加 iframe 的 session-history ,浏览器的前进、后退在不做任何处理的情况就可以直接作用于子应用
劫持 iframe 的 history.pushState 和 history.replaceState ,就可以将子应用的 url 同步到主应用的 query 参数上,当刷新浏览器初始化 iframe 时,读回子应用的 url 并使用 iframe 的 history.replaceState 进行同步
采用这种方式我们可以获得
收益
- 浏览器刷新、前进、后退都可以作用到子应用
- 实现成本低,无需复杂的监听来处理同步问题
- 多应用同时激活时也能保持路由同步
iframe 连接机制和 css 沙箱机制
无界采用 webcomponent 来实现页面的样式隔离,无界会创建一个 wujie 自定义元素,然后将子应用的完整结构渲染在内部
子应用的实例 instance 在 iframe 内运行, dom 在主应用容器下的 webcomponent 内,通过代理 iframe 的 document 到 webcomponent ,可以实现两者的互联。
将 document 的查询类接口: getElementsByTagName、getElementsByClassName、getElementsByName、getElementById、querySelector、querySelectorAll、head、body 全部代理到 webcomponent ,这样 instance 和 webcomponent 就精准的链接起来。
当子应用发生切换, iframe 保留下来,子应用的容器可能销毁,但 webcomponent 依然可以选择保留,这样等应用切换回来将 webcomponent 再挂载回容器上,子应用可以获得类似 vue 的 keep-alive 的能力.
采用这种方式我们可以获得
收益
- 天然 css 沙箱
直接物理隔离,样式隔离子应用不用做任何修改
- 天然适配弹窗问题
document.body 的 appendChild 或者 insertBefore 会代理直接插入到 webcomponent ,子应用不用做任何改造
- 子应用保活
子应用保留 iframe 和 webcomponent ,应用内部的 state 不会丢失
- 完整的 DOM 结构
webcomponent 保留了子应用完整的 html 结构,样式和结构完全对应,子应用不用做任何修改
通信机制
承载子应用的 iframe 和主应用是同域的,所以主、子应用天然就可以很好的进行通信,在无界我们提供三种通信方式
- props 注入机制
子应用通过 $wujie.props 可以轻松拿到主应用注入的数据
- window.parent 通信机制
子应用 iframe 沙箱和主应用同源,子应用可以直接通过 window.parent 和主应用通信
- 去中心化的通信机制
无界提供了 EventBus 实例,注入到主应用和子应用,所有的应用可以去中心化的进行通信
优势
通过上面原理的阐述,我们可以得出无界微前端框架的几点优势:
优势
- 多应用同时激活在线
框架具备同时激活多应用,并保持这些应用路由同步的能力
- 组件式的使用方式
无需注册,更无需路由适配,在组件内使用,跟随组件装载、卸载
- 应用级别的 keep-alive
子应用开启 保活模式 后,应用发生切换时整个子应用的状态可以保存下来不丢失,结合 预执行模式 可以获得类似 ssr 的打开体验
-
纯净无污染
-
无界利用
iframe和webcomponent来搭建天然的js隔离沙箱和css隔离沙箱 -
利用
iframe的history和主应用的history在同一个 top-level browsing context 来搭建天然的路由同步机制 -
副作用局限在沙箱内部,子应用切换无需任何清理工作,没有额外的切换成本
-
性能和体积兼具
-
子应用执行性能和原生一致,子应用实例
instance运行在iframe的window上下文中,避免with(proxyWindow){code}这样指定代码执行上下文导致的性能下降,但是多了实例化iframe的一次性的开销,可以通过 preload 提前实例化 -
体积比较轻量,借助
iframe和webcomponent来实现沙箱,有效的减小了代码量 -
开箱即用
不管是样式的兼容、路由的处理、弹窗的处理、热更新的加载,子应用完成接入即可开箱即用无需额外处理,应用 接入成本 也极低
无界入门
我们使用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>
只需要简单的几行代码就可以实现微前端应用,接入成本很低
