diff --git a/packages/plugin-qiankun/src/slave/index.ts b/packages/plugin-qiankun/src/slave/index.ts index 19f3efd5..ab943262 100644 --- a/packages/plugin-qiankun/src/slave/index.ts +++ b/packages/plugin-qiankun/src/slave/index.ts @@ -138,12 +138,25 @@ export default function (api: IApi) { '{ genMount as qiankun_genMount, genBootstrap as qiankun_genBootstrap, genUnmount as qiankun_genUnmount, genUpdate as qiankun_genUpdate }', }; }); + + api.addEntryCodeAhead( + () => + ` + const appId = window.appId = 'appId' in window ? window.appId + 1 : 0; + try { + pluginArgs.appId = appId; + } catch { + console.error(\`[@umijs/plugin-qiankun]: Cannot find pluginArgs object in current scope, plugin-qiankun will use an insecure way to handle the clientRenderOpts, see https://github.com/umijs/plugins/pull/629 for more information. \`); + } + `, + ); + api.addEntryCode( () => ` export const bootstrap = qiankun_genBootstrap(clientRender); - export const mount = qiankun_genMount('${api.config.mountElementId}'); - export const unmount = qiankun_genUnmount('${api.config.mountElementId}'); + export const mount = qiankun_genMount('${api.config.mountElementId}', appId); + export const unmount = qiankun_genUnmount('${api.config.mountElementId}', appId); export const update = qiankun_genUpdate(); if (!window.__POWERED_BY_QIANKUN__) { diff --git a/packages/plugin-qiankun/src/slave/lifecycles.ts.tpl b/packages/plugin-qiankun/src/slave/lifecycles.ts.tpl index 7abcb453..a38af0dd 100644 --- a/packages/plugin-qiankun/src/slave/lifecycles.ts.tpl +++ b/packages/plugin-qiankun/src/slave/lifecycles.ts.tpl @@ -23,7 +23,16 @@ let render = noop; let hasMountedAtLeastOnce = false; export default () => defer.promise; -export const clientRenderOptsStack: any[] = []; + +const unsafe_clientRenderOptsStack: any[] = []; // 对于尚未更新到这次提交(https://github.com/umijs/umi/pull/6702)的umijs版本的适配,以后应该删掉 +const clientRenderOptsMap: any = {}; +export function getClientRenderOpts(appId?: number) { + if (typeof appId === 'number') { + return appId in clientRenderOptsMap ? { ...clientRenderOptsMap[appId] } : undefined + } else { + return unsafe_clientRenderOptsStack.pop(); + } +} function normalizeHistory( history?: 'string' | Record, @@ -64,7 +73,7 @@ export function genBootstrap(oldRender: typeof noop) { }; } -export function genMount(mountElementId: string) { +export function genMount(mountElementId: string, appId: number) { return async (props?: any) => { // props 有值时说明应用是通过 lifecycle 被主应用唤醒的,而不是独立运行时自己 mount if (typeof props !== 'undefined') { @@ -108,7 +117,8 @@ export function genMount(mountElementId: string) { }, }; - clientRenderOptsStack.push(clientRenderOpts); + unsafe_clientRenderOptsStack.push(clientRenderOpts); + clientRenderOptsMap[appId] = clientRenderOpts; } // 第一次 mount defer 被 resolve 后umi 会自动触发 render,非第一次 mount 则需手动触发 @@ -133,7 +143,7 @@ export function genUpdate() { }; } -export function genUnmount(mountElementId: string) { +export function genUnmount(mountElementId: string, appId: number) { return async (props: any) => { const container = props?.container ? props.container.querySelector(`#${mountElementId}`) @@ -144,5 +154,7 @@ export function genUnmount(mountElementId: string) { const slaveRuntime = await getSlaveRuntime(); if (slaveRuntime.unmount) await slaveRuntime.unmount(props); + + delete clientRenderOptsMap[appId]; }; } diff --git a/packages/plugin-qiankun/src/slave/slaveRuntimePlugin.ts.tpl b/packages/plugin-qiankun/src/slave/slaveRuntimePlugin.ts.tpl index 71e1479d..334b7ffa 100644 --- a/packages/plugin-qiankun/src/slave/slaveRuntimePlugin.ts.tpl +++ b/packages/plugin-qiankun/src/slave/slaveRuntimePlugin.ts.tpl @@ -1,5 +1,5 @@ import React from 'react'; -import qiankunRender, { clientRenderOptsStack } from './lifecycles'; +import qiankunRender, { getClientRenderOpts } from './lifecycles'; import { Context } from '@@/plugin-qiankun/qiankunContext'; export function rootContainer(container: HTMLElement) { @@ -13,9 +13,9 @@ export const render = (oldRender: any) => { return qiankunRender().then(oldRender); }; -export function modifyClientRenderOpts(memo: any) { - // 每次应用 render 的时候会调 modifyClientRenderOpts,这时尝试从队列中取 render 的配置 - const clientRenderOpts = clientRenderOptsStack.shift(); +export function modifyClientRenderOpts(memo: any, args: any = {}) { + // 每次应用 render 的时候会调 modifyClientRenderOpts,这时根据当前的appId获取 render 的配置 + const clientRenderOpts = getClientRenderOpts(args.appId); if (clientRenderOpts) { const history = clientRenderOpts.getHistory(); delete clientRenderOpts.getHistory;