转载请注明出处,点击此处 查看更多精彩内容
wujie 是一个基于 Web Component
容器 + iframe
沙箱的微前端方案。能够完善的解决适配成本、样式隔离、运行性能、页面白屏、子应用通信、子应用保活、多应用激活、vite 框架支持、应用共享等问题。
主应用不限技术栈,只需引入 wujie
、配置子应用路由并启动 wujie
即可。
wujie
针对 React
和 Vue
框架分别提供了 wujie-react
wujie-vue2
wujie-vue3
依赖。这里以 Vue3
为例。
wujie
yarn add wujie-vue3
pnpm add wujie-vue3
npm i wujie-vue3
创建 Vue 页面(如 src/views/SubApp.vue
)用于承载子应用。
<template>
<div>
<WujieVue width="100%" height="100%" name="sub-app" url="http://localhost:8381/" sync />
</div>
</template>
组件配置说明:
wujie
会将子应用的 name 作为一个 url 查询参数,实时同步子应用的路径作为这个查询参数的值,这样分享 URL 或者刷新浏览器子应用路由都不会丢失。import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
...,
{
name: 'sub-app',
path: '/sub-app',
component: () => import('../views/SubApp.vue')
},
]
})
export default router
path
是子应用路由地址。
wujie
对子应用的侵入非常小,在满足跨域条件下子应用可以不用改造。
在微前端框架中,子应用放置在主应用页面中随着主应用页面的打开和关闭反复的激活和销毁,而在 wujie
中子应用是否保活以及是否进行生命周期的改造会进入完全不同的处理流程。
alive
设置为 true 时进入保活模式,内部的数据和路由的状态不会随着页面切换而丢失。alive
设置为 false 且进行了生命周期改造时进入单例模式。dom
的 Web Component
,还会销毁承载子应用 JavaScript
的 iframe
,相应的 wujie
实例和子应用实例都会被销毁。let app;
function renderApp() {
app = new Vue({
router,
store,
render: (h) => h(App),
});
app.$mount("#app");
}
function destroyApp() {
app.$destroy();
}
if (window.__POWERED_BY_WUJIE__) {
window.__WUJIE_MOUNT = renderApp;
window.__WUJIE_UNMOUNT = destroyApp;
// // Vite 需要主动调用 wujie 的渲染函数
// window.__WUJIE.mount();
} else {
renderApp();
}
如果子应用的实例化是在异步函数中进行的(如 Vite
),在定义完生命周期函数后,需要主动调用 wujie
的渲染函数 window.__WUJIE.mount()
。
wujie
提供三种通信方式。
主应用可以通过 props
注入数据和方法:
<WujieVue name="xxx" url="xxx" :props="{ data: xxx, methods: xxx }"></WujieVue>
子应用可以通过 $wujie
对象来获取数据:
const props = window.$wujie?.props;
wujie
提供一套去中心化的通信方案,主应用和子应用、子应用和子应用都可以通过这种方式方便的进行通信, 详见 api
获取 bus
实例:
// 主应用
import WujieVue from "wujie-vue";
const { bus } = WujieVue;
// 子应用
window.$wujie?.bus
通信方法:
// 监听事件
bus.$on("事件名字", (arg1, arg2, ...) => {});
// 发送事件
bus.$emit("事件名字", arg1, arg2, ...);
// 取消事件监听
bus.$off("事件名字", (arg1, arg2, ...) => {});
由于子应用运行的 iframe
的 src
和主应用是同域的,所以相互可以直接通信。
主应用调用子应用的全局数据:
window.document.querySelector("iframe[name=子应用id]").contentWindow.xxx;
子应用调用主应用的全局数据:
window.parent.xxx;
子应用通过 v-html
、innerHtml
或者在 template
中动态添加 style
时,框架默认的 plugin
无法处理这种场景。可通过动态资源路径解决。
src
目录新增 public-path.js
:if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
index.js
顶部导入 public-path.js
。import "./public-path";
通过 window.__WUJIE_RAW_WINDOW__
获取真实的 window
对象。
问题描述:
GitHub Issues:
问题原因:
iframe
拥有自己的路由栈,切换子应用导致 iframe
被销毁,重新进入子应用时创建新的 iframe
,路由栈丢失。
解决方案:
暂无