·前言
所谓微前端,就是把一个应用当成vue
组件嵌入到另一个应用。将一个页面拆分成独立的小型应用,各个应用间相互独立,可以随意组合,更加灵活。原生比较常用的方案是使用iframe,但是这种方案存在一些缺点,如:dom隔离严重、路由无法保活、父子应用通讯困难等。
本文将介绍一种基于iframe的全新微前端方案 -- 【无界】,解决了上述问题外还具有成本低、速度快、原生隔离、功能强等优点。
·无界
以下介绍在 Vue3 项目中如何应用无界嵌入子应用:
1. 安装
npm i wujie-vue3 -S
2. 在 main.ts 挂载使用
import { createApp } from 'vue';
import WujieVue from 'wujie-vue3';
import App from './App.vue';
const app = createApp(App);
app.use(WujieVue).mount('#app');
3. 在页面中应用
<template>
<WujieVue
width="100%"
height="100%"
name="server"
:url="serverUrl"
:alive="true"
:sync="true"
:after-mount="afterMount"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import wujieVue from 'wujie-vue3';
import { environment } from '@/app.config';
const serverUrl = ref(environment.VITE_SERVER_URL);
const afterMount = () => {};
</script>
<style scoped lang="scss"></style>
其中,name 为子应用唯一标识符,url 为子应用的路径地址,alive 设为 true 则是保活模式,after-mount 为子应用渲染后的生命周期钩子,无界的主要生命周期可以分为:
- beforeLoad:子应用开始加载静态资源前触发
- beforeMount:子应用渲染(调用
window.__WUJIE_MOUNT
)前触发 - afterMount:子应用渲染(调用
window.__WUJIE_MOUNT
)后触发 - beforeUnmount:子应用卸载(调用
window.__WUJIE_UNMOUNT
)前触发 - afterUnmount: 子应用卸载(调用
window.__WUJIE_UNMOUNT
)后触发 - activated:子应用保活模式下,进入时触发
- deactivated:子应用保活模式下,离开时触发
几种模式的区别:
- 保活模式:子应用的alive设置为
true
时进入保活模式,内部的数据和路由的状态不会随着页面切换而丢失。在保活模式下,子应用只会进行一次渲染,页面发生切换时承载子应用dom
的webcomponent
会保留在内存中,当子应用重新激活时无界会将内存中的webcomponent
重新挂载到容器上。保活模式下改变 子应用的路由不会发生变化,需要采用通信的方式对子应用路由进行跳转 - 单例模式:子应用的
alive
为false
且进行了生命周期改造时进入单例模式。子应用页面如果切走,会调用window.__WUJIE_UNMOUNT
销毁子应用当前实例,子应用页面如果切换回来,会调用window.__WUJIE_MOUNT
渲染子应用新的子应用实例在单例式下,改变 url 子应用的路由会发生跳转到对应路由。如果主应用上有多个菜单栏用到了子应用的不同页面,在每个页面启动该子应用的时候将
name
设置为同一个,这样可以共享一个wujie
实例,承载子应用js
的iframe
也实现了共享,不同页面子应用的url
不同,切换这个子应用的过程相当于:销毁当前应用实例 => 同步新路由 => 创建新应用实例 - 重建模式:子应用既没有设置为保活模式,也没有进行生命周期的改造则进入了重建模式,每次页面切换不仅会销毁承载子应用
dom
的webcomponent
,还会销毁承载子应用js
的iframe
,相应的wujie
实例和子应用实例都会被销毁。重建模式下改变 url 子应用的路由会跳转对应路由,但是在路由同步场景并且子应用的路由同步参数已经同步到主应用url
上时则无法生效,因为改变url
后会导致子应用销毁重新渲染,此时如果有同步参数则同步参数的优先级最高
4. 父子应用通信
承载子应用的iframe
和主应用是同域的,所以主、子应用天然就可以很好的进行通信,在无界中提供三种通信方式:
- props 通信
主应用可以通过props注入数据和方法:
<WujieVue name="xxx" url="xxx" :props="{ data: xxx, methods: xxx }"></WujieVue>
子应用可以通过$wujie来获取:
const props = window.$wujie?.props; // {data: xxx, methods: xxx}
- window 通信
主应用调用子应用的全局数据
window.document.querySelector("iframe[name=子应用id]").contentWindow.xxx;
子应用调用主应用的全局数据
window.parent.xxx;
- eventBus 通信
无界提供一套去中心化的通信方案,主应用和子应用、子应用和子应用都可以通过这种方式方便的进行通信,主应用使用方式:
// 如果使用wujie
import { bus } from "wujie";
// 如果使用wujie-vue
import WujieVue from "wujie-vue";
const { bus } = WujieVue;
// 如果使用wujie-react
import WujieReact from "wujie-react";
const { bus } = WujieReact;
// 主应用监听事件
bus.$on("事件名字", function (arg1, arg2, ...) {});
// 主应用发送事件
bus.$emit("事件名字", arg1, arg2, ...);
// 主应用取消事件监听
bus.$off("事件名字", function (arg1, arg2, ...) {});
子应用使用方式:
// 子应用监听事件
window.$wujie?.bus.$on("事件名字", function (arg1, arg2, ...) {});
// 子应用发送事件
window.$wujie?.bus.$emit("事件名字", arg1, arg2, ...);
// 子应用取消事件监听
window.$wujie?.bus.$off("事件名字", function (arg1, arg2, ...) {});
·总结
总的来说无界的优点还是很明显:
- 使用
iframe
作为天然的js
沙箱,不会污染主应用环境 - 使用 Web Components 来隔离
html
、css
,这是一个浏览器原生支持的组件封装技术,可以有效隔离元素之间的样式 - 提供了事件总线和props传参,弥补了iframe通信困难的缺点
- 子应用无需做任何改造,接入更简单
- 实现了多应用激活、应用保活功能
- 提供了vue和react组件的封装,开箱即用
以上就是在Vue3项目中使用微前端无界的相关介绍,目前比较流行的微前端框架还有乾坤(single-spa的进一步优化),感兴趣的小伙伴可以自行去了解 ^-^