Skip to content

Commit

Permalink
fix(sandbox): compatible with dynamically appending scripts to detach…
Browse files Browse the repository at this point in the history
…ed containers (#2857)

* fix(sandbox): compatible with dynamically appending scripts to detached containers

* Update packages/sandbox/src/patchers/dynamicAppend/common.ts

* Create wise-eagles-tease.md
  • Loading branch information
kuitos authored Dec 25, 2023
1 parent 9ec1595 commit 9082546
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/wise-eagles-tease.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@qiankunjs/sandbox": patch
---

fix(sandbox): compatible with dynamically appending scripts to detached containers
23 changes: 21 additions & 2 deletions packages/sandbox/src/patchers/dynamicAppend/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { AssetsTranspilerOpts, ScriptTranspilerOpts } from '@qiankunjs/shar
* @author Kuitos
* @since 2019-10-21
*/
import { prepareDeferredQueue } from '@qiankunjs/shared';
import { prepareDeferredQueue, warn } from '@qiankunjs/shared';
import { qiankunHeadTagName } from '../../consts';
import type { SandboxConfig } from './types';

Expand Down Expand Up @@ -201,7 +201,26 @@ export function getOverwrittenAppendChildOrInsertBefore(

const transpiledScriptElement = nodeTransformer(scriptElement, transformerOpts);

const result = appendChild.call(this, transpiledScriptElement, refChild) as T;
/*
The target container of script element might be removed from current document.
For example, the main application clears the DOM first during route switching, and then trigger unmount,
at this time, the micro app may still be processing the logic of the route switching, and try to add nodes to the detached container,
in this scenario, we have to append the script to global document head to trigger script evaluation
*/
const scriptTargetDetached = !document.contains(this);
if (scriptTargetDetached) {
warn(
`Trying to append script element ${
transpiledScriptElement.src || transpiledScriptElement.dataset.src
} to a detached container which may cause unexpected behaviors!`,
);
}
/*
FIXME we have to set the target container to global document head to trigger script evaluation while the real container was detached,
as dynamic append script element to detached element will not trigger script evaluation automatically
*/
const targetContainerDOM = scriptTargetDetached ? document.head : this;
const result = appendChild.call(targetContainerDOM, transpiledScriptElement, refChild) as T;

// the script have no src attribute after transpile, indicating that the script needs to wait for the src to be filled
if (externalSyncMode && !transpiledScriptElement.hasAttribute('src')) {
Expand Down

0 comments on commit 9082546

Please sign in to comment.