From cbad8c8d7d0254651eb75effbe2aac3a2310b33b Mon Sep 17 00:00:00 2001 From: Kuitos Date: Thu, 16 Sep 2021 16:15:33 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20compute=20container=20xpath=20at?= =?UTF-8?q?=20beginning=20to=20keep=20it=20consist=20around=20app=20runnin?= =?UTF-8?q?g=20(#1725)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis.ts | 59 ++++++++++++++++++++++------------------------------ src/utils.ts | 11 ++++++++++ 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/apis.ts b/src/apis.ts index 32d79c9..f81d5db 100644 --- a/src/apis.ts +++ b/src/apis.ts @@ -1,12 +1,18 @@ import { noop } from 'lodash'; import type { ParcelConfigObject } from 'single-spa'; import { mountRootParcel, registerApplication, start as startSingleSpa } from 'single-spa'; -import type { ObjectType } from './interfaces'; -import type { FrameworkConfiguration, FrameworkLifeCycles, LoadableApp, MicroApp, RegistrableApp } from './interfaces'; +import type { + FrameworkConfiguration, + FrameworkLifeCycles, + LoadableApp, + MicroApp, + ObjectType, + RegistrableApp, +} from './interfaces'; import type { ParcelConfigObjectGetter } from './loader'; import { loadApp } from './loader'; import { doPrefetchStrategy } from './prefetch'; -import { Deferred, getContainer, getXPathForElement, toArray } from './utils'; +import { Deferred, getContainerXPath, toArray } from './utils'; let microApps: Array>> = []; @@ -80,24 +86,18 @@ export function loadMicroApp( ): MicroApp { const { props, name } = app; - const getContainerXpath = (container: string | HTMLElement): string | void => { - const containerElement = getContainer(container); - if (containerElement) { - return getXPathForElement(containerElement, document); - } - - return undefined; - }; + const container = 'container' in app ? app.container : undefined; + // Must compute the container xpath at beginning to keep it consist around app running + // If we compute it every time, the container dom structure most probably been changed and result in a different xpath value + const containerXPath = getContainerXPath(container); + const appContainerXPathKey = `${name}-${containerXPath}`; let microApp: MicroApp; const wrapParcelConfigForRemount = (config: ParcelConfigObject): ParcelConfigObject => { - const container = 'container' in app ? app.container : undefined; - let microAppConfig = config; if (container) { - const xpath = getContainerXpath(container); - if (xpath) { - const containerMicroApps = containerMicroAppsMap.get(`${name}-${xpath}`); + if (containerXPath) { + const containerMicroApps = containerMicroAppsMap.get(appContainerXPathKey); if (containerMicroApps?.length) { const mount = [ async () => { @@ -137,7 +137,6 @@ export function loadMicroApp( configuration ?? { ...frameworkConfiguration, singular: false }, ); const { $$cacheLifecycleByAppName } = userConfiguration; - const container = 'container' in app ? app.container : undefined; if (container) { // using appName as cache for internal experimental scenario @@ -146,9 +145,8 @@ export function loadMicroApp( if (parcelConfigGetterPromise) return wrapParcelConfigForRemount((await parcelConfigGetterPromise)(container)); } - const xpath = getContainerXpath(container); - if (xpath) { - const parcelConfigGetterPromise = appConfigPromiseGetterMap.get(`${name}-${xpath}`); + if (containerXPath) { + const parcelConfigGetterPromise = appConfigPromiseGetterMap.get(appContainerXPathKey); if (parcelConfigGetterPromise) return wrapParcelConfigForRemount((await parcelConfigGetterPromise)(container)); } } @@ -158,10 +156,7 @@ export function loadMicroApp( if (container) { if ($$cacheLifecycleByAppName) { appConfigPromiseGetterMap.set(name, parcelConfigObjectGetterPromise); - } else { - const xpath = getContainerXpath(container); - if (xpath) appConfigPromiseGetterMap.set(`${name}-${xpath}`, parcelConfigObjectGetterPromise); - } + } else if (containerXPath) appConfigPromiseGetterMap.set(appContainerXPathKey, parcelConfigObjectGetterPromise); } return (await parcelConfigObjectGetterPromise)(container); @@ -177,18 +172,14 @@ export function loadMicroApp( microApp = mountRootParcel(memorizedLoadingFn, { domElement: document.createElement('div'), ...props }); - // Store the microApps which they mounted on the same container - const container = 'container' in app ? app.container : undefined; if (container) { - const xpath = getContainerXpath(container); - if (xpath) { - const key = `${name}-${xpath}`; - - const microAppsRef = containerMicroAppsMap.get(key) || []; + if (containerXPath) { + // Store the microApps which they mounted on the same container + const microAppsRef = containerMicroAppsMap.get(appContainerXPathKey) || []; microAppsRef.push(microApp); - containerMicroAppsMap.set(key, microAppsRef); + containerMicroAppsMap.set(appContainerXPathKey, microAppsRef); - const cleanApp = () => { + const cleanup = () => { const index = microAppsRef.indexOf(microApp); microAppsRef.splice(index, 1); // @ts-ignore @@ -196,7 +187,7 @@ export function loadMicroApp( }; // gc after unmount - microApp.unmountPromise.then(cleanApp).catch(cleanApp); + microApp.unmountPromise.then(cleanup).catch(cleanup); } } diff --git a/src/utils.ts b/src/utils.ts index 0b0ea75..0c37508 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -215,3 +215,14 @@ export function getXPathForElement(el: Node, document: Document): string | void export function getContainer(container: string | HTMLElement): HTMLElement | null { return typeof container === 'string' ? document.querySelector(container) : container; } + +export function getContainerXPath(container?: string | HTMLElement): string | void { + if (container) { + const containerElement = getContainer(container); + if (containerElement) { + return getXPathForElement(containerElement, document); + } + } + + return undefined; +}