目录
无界方案
应用加载机制和 js 沙箱机制
路由同步机制
iframe 连接机制和 css 沙箱机制
通信机制
优势
无界入门
无界方案
在乾坤的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>
只需要简单的几行代码就可以实现微前端应用,接入成本很低