umijs / qiankun

📦 🚀 Blazing fast, simple and complete solution for micro frontends.
https://qiankun.umijs.org
MIT License
15.77k stars 2.01k forks source link

loadMicroApp 同时加载多个微应用渲染只显示某一个 #2938

Closed 2232390565 closed 6 months ago

2232390565 commented 6 months ago

What happens?

使用loadMicroApp同时加载多个微应用,只渲染某一个, 但是按顺序加载则都可以展示

复现步骤,错误日志以及相关配置

index.ts

const apps = microApps.map((item) => ({
  {
    name: 'microApp',
    entry: 'http://localhost:9201',
    container: '#microApp',
    activeRule: () => true, // 始终激活
  },
  { 
    name: 'microFederation',
    entry: 'http://localhost:9202',
    container: '#microFederation',
    activeRule: () => true, // 始终激活
  },
}));

interface MicroParams {
  appName: string
  parentContain?: Element
  callback: () => void
}

// 创建微应用容器
const createMicroEle = ({appName, parentContain}:  Pick<MicroParams, 'appName' | 'parentContain'>) => {
  return new Promise((resolve) => {
    const _parentContain = parentContain && typeof parentContain === 'string' ? document.querySelector(parentContain) : parentContain
    const parent = (_parentContain ?? document.querySelector('#app')) || document.body
    console.log({appName, parentContain}, '--');

    const container = document.createElement('div');
    container.id = appName; // 使用微应用的名称作为容器元素的 id
    parent.appendChild(container);
    resolve(container)
  })
}

const registerMicro = (app: any, parentContain: MicroParams['parentContain']):Promise<MicroApp> => new Promise(async (resolve) =>{
  const container = await createMicroEle({ appName: app.name, parentContain});
  const micro = await loadMicroApp(
    app,
    {
      singular: false,  // 单实例指的是同一时间只会渲染一个微应用
      sandbox: { //是否开启沙箱,
        strictStyleIsolation: true, //样式隔离特性 div[data-qiankun-${appName}]
      },
    }
  );
  resolve(micro)
})

export const createMicro = async (micros: MicroParams[] | MicroParams) => {
  const microStore = useMicroStore();
  let _micros = Array.isArray(micros) ? micros : [micros]
  const microNames = _micros.map(app => app.appName)

  // 过滤没有的微应用
  const _apps = apps.filter(app => microNames.includes(app.name))

  const microsPromises = _micros.map((ite) => {
    return registerMicro(_apps.find(app => app.name === ite.appName), ite.parentContain);
  });

  const microInstances = await Promise.all(microsPromises);
  console.log(microInstances);

  // Callback after all micro apps are loaded
  microInstances.forEach((micro, index) => {
    micro.mountPromise.then(() => {
      microStore.addMicroList(_micros[index].appName, micro)
      _micros[index].callback();
    });
  });
};

index.vue

<template>
  <div ref="HomeRef"></div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { createMicro } from "@/micro-app";
const HomeRef = ref();
onMounted(async () => {
  await createMicro([
    {
      appName: "microApp",
      parentContain: HomeRef.value,
      callback: () => console.log("microApp loaded"),
    },
    {
      appName: "microFederation",
      parentContain: HomeRef.value,
      callback: () => console.log("microFederation loaded"),
    },
  ]);
});

相关环境信息

github-actions[bot] commented 6 months ago

由于缺乏足够的信息(github、stackblitz、codesandbox等可复现仓库),我们暂时关闭了该 Issue。请修改(不要回复) Issue 提供最小重现以重新开启。谢谢。如果只是单独的技术咨询,可移步 https://qiankun.umijs.org/#-community 交流~