diff --git a/examples/main/multiple.js b/examples/main/multiple.js index bc7c61eb4..78f8d0713 100644 --- a/examples/main/multiple.js +++ b/examples/main/multiple.js @@ -3,7 +3,10 @@ import { loadMicroApp } from '../../es'; let app; function mount() { - app = loadMicroApp({ name: 'react15', entry: '//localhost:7102', container: '#react15' }); + app = loadMicroApp( + { name: 'react15', entry: '//localhost:7102', container: '#react15' }, + { sandbox: { experimentalStyleIsolation: true } }, + ); } function unmount() { diff --git a/src/apis.ts b/src/apis.ts index eb7daf3f3..ade6fa0ea 100644 --- a/src/apis.ts +++ b/src/apis.ts @@ -44,7 +44,7 @@ export function registerMicroApps( }); } -const appConfigPormiseGetterMap = new Map>(); +const appConfigPromiseGetterMap = new Map>(); export function loadMicroApp( app: LoadableApp, @@ -62,33 +62,46 @@ export function loadMicroApp( return undefined; }; + const wrapParcelConfigForRemount = (config: ParcelConfigObject): ParcelConfigObject => { + return { + ...config, + // empty bootstrap hook which should not run twice while it calling from cached micro app + bootstrap: () => Promise.resolve(), + }; + }; + /** * using name + container xpath as the micro app instance id, * it means if you rendering a micro app to a dom which have been rendered before, * the micro app would not load and evaluate its lifecycles again */ const memorizedLoadingFn = async (): Promise => { + const { $$cacheLifecycleByAppName } = configuration ?? frameworkConfiguration; const container = 'container' in app ? app.container : undefined; + if (container) { + // using appName as cache for internal experimental scenario + if ($$cacheLifecycleByAppName) { + const parcelConfigGetterPromise = appConfigPromiseGetterMap.get(name); + if (parcelConfigGetterPromise) return wrapParcelConfigForRemount((await parcelConfigGetterPromise)(container)); + } + const xpath = getContainerXpath(container); if (xpath) { - const parcelConfigGetterPromise = appConfigPormiseGetterMap.get(`${name}-${xpath}`); - if (parcelConfigGetterPromise) { - const parcelConfig = (await parcelConfigGetterPromise)(container); - return { - ...parcelConfig, - // empty bootstrap hook which should not run twice while it calling from cached micro app - bootstrap: () => Promise.resolve(), - }; - } + const parcelConfigGetterPromise = appConfigPromiseGetterMap.get(`${name}-${xpath}`); + if (parcelConfigGetterPromise) return wrapParcelConfigForRemount((await parcelConfigGetterPromise)(container)); } } const parcelConfigObjectGetterPromise = loadApp(app, configuration ?? frameworkConfiguration, lifeCycles); if (container) { - const xpath = getContainerXpath(container); - if (xpath) appConfigPormiseGetterMap.set(`${name}-${xpath}`, parcelConfigObjectGetterPromise); + if ($$cacheLifecycleByAppName) { + appConfigPromiseGetterMap.set(name, parcelConfigObjectGetterPromise); + } else { + const xpath = getContainerXpath(container); + if (xpath) appConfigPromiseGetterMap.set(`${name}-${xpath}`, parcelConfigObjectGetterPromise); + } } return (await parcelConfigObjectGetterPromise)(container); diff --git a/src/interfaces.ts b/src/interfaces.ts index ddc603d3f..91c53eab7 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -54,6 +54,10 @@ export type PrefetchStrategy = | ((apps: AppMetadata[]) => { criticalAppNames: string[]; minorAppsName: string[] }); type QiankunSpecialOpts = { + /** + * @deprecated internal api, don't used it as normal, might be removed after next version + */ + $$cacheLifecycleByAppName?: boolean; prefetch?: PrefetchStrategy; sandbox?: | boolean diff --git a/src/sandbox/patchers/dynamicAppend/common.ts b/src/sandbox/patchers/dynamicAppend/common.ts index c07f4517e..79f2fb9d7 100644 --- a/src/sandbox/patchers/dynamicAppend/common.ts +++ b/src/sandbox/patchers/dynamicAppend/common.ts @@ -353,7 +353,6 @@ export function rebuildCSSRules( ) { styleSheetElements.forEach((stylesheetElement) => { // re-append the dynamic stylesheet to sub-app container - // Using document.head.appendChild ensures that appendChild invocation can also directly use the HTMLHeadElement.prototype.appendChild method which is overwritten at mounting phase reAppendElement(stylesheetElement); /*