跳到主要内容

vite-vue3-JSEntry-HTMLEntry-loadMicroApp

2024年03月21日
柏拉文
越努力,越幸运

一、认识


二、实现


2.1 src/qiankun.config.ts

import { loadMicroApp, initGlobalState, MicroApp } from "qiankun";
import microAppMap from "./microApp";

interface GlobalStateType {
base: string;
mode: "hash" | "history";
name: MicroAppType;
operation: "mount" | "unmount" | "reload";
mountContainer: string;
iframeUrl?: string;
}
interface MountedMicroAppMapType {
[key: string]: MicroApp;
}
type MicroAppType = keyof typeof microAppMap;

const globalState = {
name: "",
operation: "mount",
};
const actions = initGlobalState(globalState);
const mountedMicroAppMap: MountedMicroAppMapType = {};

function excludeAssetFilter(assetUrl: string) {
const whiteList: any[] = [];
const whiteWords = ["map.qq.com", "webapi.amap"];
if (whiteList.includes(assetUrl)) {
return true;
}
return whiteWords.some((keyWord) => {
return assetUrl.includes(keyWord);
});
}
async function handleMount(state: GlobalStateType) {
const { name, base, mode, iframeUrl, mountContainer } = state;
const mountedMicroApp = mountedMicroAppMap[name];
if (mountedMicroApp) {
await mountedMicroApp.mount();
return;
}
const microApp = microAppMap[name];
microApp.props = {
...microApp.props,
base,
mode,
iframeUrl,
mountContainer,
};
mountedMicroAppMap[name] = loadMicroApp(microApp, {
singular: false,
sandbox: {
experimentalStyleIsolation: false,
},
excludeAssetFilter,
});
}
async function handleUnmount(state: GlobalStateType) {
const { name } = state;
const mountedMicroApp = mountedMicroAppMap[name];
if (mountedMicroApp) {
await mountedMicroApp.unmount();
return;
}
}
async function handleReload(state: GlobalStateType) {
const { name } = state;
const mountedMicroApp = mountedMicroAppMap[name];
if (mountedMicroApp) {
await mountedMicroApp.unmount();
await mountedMicroApp.mount();
return;
}
}
function handleStateChange(
newState: GlobalStateType,
prevState: GlobalStateType
) {
const { operation } = newState;
switch (operation) {
case "mount":
handleMount(newState);
break;
case "unmount":
handleUnmount(newState);
break;
case "reload":
handleReload(newState);
break;
}
}
function watchGlobalState() {
actions.onGlobalStateChange((newState, prevState) => {
handleStateChange(
newState as GlobalStateType,
prevState as GlobalStateType
);
});
}

function start() {
watchGlobalState();
}

export { start, actions };

2.2 src/microApp.ts

const microAppMap = {
"qiankun-htmlEntry-micro-app-vue3": {
name: "qiankun-htmlEntry-micro-app-vue3",
entry: {
html: '<div id="qiankun-htmlEntry-micro-app-vue3"></div>',
scripts: [
"https://bolawen.github.io/MicroFrontEnd/QianKun/micro-app-vue3/output/micro-app-vue3.umd.e24ae3b4.js",
],
styles: [],
},
container: "#qiankun-htmlEntry-micro-app-vue3",
props: {},
},
"qiankun-htmlEntry-micro-app-react": {
name: "qiankun-htmlEntry-micro-app-react",
entry: {
html: '<div id="qiankun-htmlEntry-micro-app-react"></div>',
scripts: [
"https://bolawen.github.io/MicroFrontEnd/QianKun/micro-app-react/output/micro-app-react.umd.fb81bbbf.js",
],
styles: [],
},
container: "#qiankun-htmlEntry-micro-app-react",
props: {},
},
"qiankun-JSEntry-micro-app-react": {
name: "qiankun-JSEntry-micro-app-react",
entry: "/qiankunMicroApp?name=qiankun-JSEntry-micro-app-react",
container: "#qiankun-JSEntry-micro-app-react",
props: {},
},
"singleSpa-JSEntry-micro-app-react": {
name: "singleSpa-JSEntry-micro-app-react",
entry: "/singleSpaTransformQiankun?name=singleSpa-JSEntry-micro-app-react",
container: "#singleSpa-JSEntry-micro-app-react",
props: {},
},
"iframe-JSEntry-micro-app-vue3": {
name: "iframe-JSEntry-micro-app-vue3",
entry: {
html: '<div id="iframe-JSEntry-micro-app-vue3"></div>',
scripts: [
"https://bolawen.github.io/MicroFrontEnd/QianKun/micro-app-iframe/output/micro-app-iframe.umd.44f0d883.js",
],
styles: [],
},
container: "#iframe-JSEntry-micro-app-vue3",
props: {},
},
};

export default microAppMap;

2.3 src/main.ts

import { createApp } from "vue";
import App from "./App.vue";
import createRouter from "./router";
import { start, actions } from "./qiankun.config";
import packageInfo from "../package.json";

const app = createApp(App);
app.use(createRouter("history", "/"));
app.mount(`#${packageInfo.name}`);
start();
window.actions = actions;

2.4 src/router.ts

import {
createRouter,
createWebHashHistory,
createWebHistory,
Router,
} from "vue-router";

import Home from "./Home.vue";
import Content from "./Content.vue";

const routes = [
{
path: "/",
name: "home",
component: Home,
},
{
path: "/content/:microApp*",
name: "Content",
component: Content,
},
];

export default function create(mode?: string, base?: string): Router {
return createRouter({
history:
mode === "history" ? createWebHistory(base) : createWebHashHistory(base),
routes,
});
}

2.5 src/App.vue

<template>
<div>
<h3>Main-App-Vue3 基座</h3>
<div>
<router-link to="/">首页</router-link>
<router-link to="/content">内容</router-link>
</div>
<router-view />
</div>
</template>

2.6 src/Content.vue

<template>
<div class="home">内容</div>
<div>
<button
@click="handleChangeMicro('qiankun-htmlEntry-micro-app-vue3', 'qiankun')"
>
qiankun HTML-Entry micro-app-vue3 微应用
</button>
<button
@click="handleChangeMicro('qiankun-htmlEntry-micro-app-react', 'qiankun')"
>
qiankun HTML-Entry micro-app-react 微应用
</button>
<button
@click="handleChangeMicro('qiankun-JSEntry-micro-app-react', 'qiankun')"
>
qiankun JS-Entry micro-app-vue3 微应用
</button>
<button
@click="
handleChangeMicro('singleSpa-JSEntry-micro-app-react', 'single-spa')
"
>
single-spa JS-Entry micro-app-react 微应用
</button>
<button
@click="handleChangeMicro('iframe-JSEntry-micro-app-vue3', 'iframe')"
>
iframe JS-Entry micro-app-vue3 微应用
</button>
</div>
<div ref="microAppParentContainer"></div>
</template>

<script setup lang="ts">
import { ref, nextTick } from "vue";

const microAppParentContainer = ref();

function handleChangeMicro(microApp: string, type: string) {
const microAppContainer = document.createElement("div");
microAppContainer.id = microApp;
microAppParentContainer.value.append(microAppContainer);

const qiankunProps = {
base: "/content",
mode: "history",
type,
mountContainer: microApp,
};

if (type === "iframe") {
qiankunProps.iframeUrl = "https://qiankun.umijs.org/zh";
}

nextTick(() => {
const globalState = {
name: microApp,
operation: "mount",
...qiankunProps,
};
window.actions.setGlobalState(globalState);
});
}
</script>