Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(qiankun): 尝试修复嵌入主应用的子应用的热更新问题 #629

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions packages/plugin-qiankun/src/slave/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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__) {
Expand Down
20 changes: 16 additions & 4 deletions packages/plugin-qiankun/src/slave/lifecycles.ts.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, any>,
Expand Down Expand Up @@ -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') {
Expand Down Expand Up @@ -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 则需手动触发
Expand All @@ -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}`)
Expand All @@ -144,5 +154,7 @@ export function genUnmount(mountElementId: string) {

const slaveRuntime = await getSlaveRuntime();
if (slaveRuntime.unmount) await slaveRuntime.unmount(props);

delete clientRenderOptsMap[appId];
};
}
8 changes: 4 additions & 4 deletions packages/plugin-qiankun/src/slave/slaveRuntimePlugin.ts.tpl
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -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;
Expand Down