Skip to content

Commit 76e192f

Browse files
committed
feat: 修复issue-1519 && 添加自定义屏蔽js加载异常钩子
1 parent e165d7b commit 76e192f

5 files changed

Lines changed: 56 additions & 46 deletions

File tree

src/libs/utils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ export function isVideoElement(target: unknown): target is HTMLVideoElement {
144144
export function isLinkElement(target: unknown): target is HTMLLinkElement {
145145
return toTypeString(target) === '[object HTMLLinkElement]'
146146
}
147+
export function isBodyElement(target: unknown): target is HTMLBodyElement {
148+
return toTypeString(target) === '[object HTMLBodyElement]'
149+
}
147150

148151
export function isStyleElement(target: unknown): target is HTMLStyleElement {
149152
return toTypeString(target) === '[object HTMLStyleElement]'

src/sandbox/iframe/document.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ function patchDocumentProperty (
306306
get: () => {
307307
throttleDeferForIframeAppName(appName)
308308
if (tagName === 'body') {
309-
return sandbox.options.container?.querySelector('micro-app-body')
309+
return sandbox.options.container?.querySelector('micro-app-body') || rawDocument[tagName]
310310
}
311311
return rawDocument[tagName]
312312
},

src/source/index.ts

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ import {
44
CompletionPath,
55
injectFiberTask,
66
serialExecFiberTasks,
7-
isLinkElement,
8-
isScriptElement,
9-
isStyleElement,
10-
isImageElement,
7+
isBodyElement,
118
} from '../libs/utils'
129
import {
1310
extractLinkFromHtml,
@@ -24,62 +21,64 @@ import globalEnv from '../libs/global_env'
2421

2522
/**
2623
* Recursively process each child element
27-
* @param parent parent element
24+
* @param body body element
2825
* @param app app
2926
* @param microAppHead micro-app-head element
3027
*/
31-
function flatChildren (
32-
parent: HTMLElement,
28+
function flatBodyChildren(
29+
body: HTMLElement,
3330
app: AppInterface,
34-
microAppHead: Element,
3531
fiberStyleTasks: fiberTasks,
3632
): void {
37-
const children = Array.from(parent.children)
33+
if (!body || !isBodyElement(body)) {
34+
return
35+
}
36+
const links = Array.from(body.getElementsByTagName('link'))
37+
38+
links.map((dom) => {
39+
if (dom.hasAttribute('exclude') || checkExcludeUrl(dom.getAttribute('href'), app.name)) {
40+
dom.parentElement!.replaceChild(document.createComment('link element with exclude attribute ignored by micro-app'), dom)
41+
} else if (!(dom.hasAttribute('ignore') || checkIgnoreUrl(dom.getAttribute('href'), app.name))) {
42+
extractLinkFromHtml(dom, dom.parentElement, app)
43+
} else if (dom.hasAttribute('href')) {
44+
globalEnv.rawSetAttribute.call(dom, 'href', CompletionPath(dom.getAttribute('href')!, app.url))
45+
}
46+
return dom
47+
})
48+
49+
const styles = Array.from(body.getElementsByTagName('style'))
3850

39-
children.length && children.forEach((child) => {
40-
flatChildren(child as HTMLElement, app, microAppHead, fiberStyleTasks)
51+
styles.map((dom) => {
52+
if (dom.hasAttribute('exclude')) {
53+
dom.parentElement!.replaceChild(document.createComment('style element with exclude attribute ignored by micro-app'), dom)
54+
} else if (app.scopecss && !dom.hasAttribute('ignore')) {
55+
injectFiberTask(fiberStyleTasks, () => scopedCSS(dom, app))
56+
}
57+
return dom
4158
})
4259

43-
for (const dom of children) {
44-
if (isLinkElement(dom)) {
45-
if (dom.hasAttribute('exclude') || checkExcludeUrl(dom.getAttribute('href'), app.name)) {
46-
parent.replaceChild(document.createComment('link element with exclude attribute ignored by micro-app'), dom)
47-
} else if (!(dom.hasAttribute('ignore') || checkIgnoreUrl(dom.getAttribute('href'), app.name))) {
48-
extractLinkFromHtml(dom, parent, app)
49-
} else if (dom.hasAttribute('href')) {
50-
globalEnv.rawSetAttribute.call(dom, 'href', CompletionPath(dom.getAttribute('href')!, app.url))
51-
}
52-
} else if (isStyleElement(dom)) {
53-
if (dom.hasAttribute('exclude')) {
54-
parent.replaceChild(document.createComment('style element with exclude attribute ignored by micro-app'), dom)
55-
} else if (app.scopecss && !dom.hasAttribute('ignore')) {
56-
injectFiberTask(fiberStyleTasks, () => scopedCSS(dom, app))
57-
}
58-
} else if (isScriptElement(dom)) {
59-
extractScriptElement(dom, parent, app)
60-
} else if (isImageElement(dom) && dom.hasAttribute('src')) {
60+
const scripts = Array.from(body.getElementsByTagName('script'))
61+
62+
scripts.map((dom) => {
63+
extractScriptElement(dom, dom.parentElement, app)
64+
return dom
65+
})
66+
const images = Array.from(body.getElementsByTagName('img'))
67+
68+
images.map((dom) => {
69+
if (dom.hasAttribute('src')) {
6170
globalEnv.rawSetAttribute.call(dom, 'src', CompletionPath(dom.getAttribute('src')!, app.url))
6271
}
63-
/**
64-
* Don't remove meta and title, they have some special scenes
65-
* e.g.
66-
* document.querySelector('meta[name="viewport"]') // for flexible
67-
* document.querySelector('meta[name="baseurl"]').baseurl // for api request
68-
*
69-
* Title point to main app title, child app title used to be compatible with some special scenes
70-
*/
71-
// else if (dom instanceof HTMLMetaElement || dom instanceof HTMLTitleElement) {
72-
// parent.removeChild(dom)
73-
// }
74-
}
72+
return dom
73+
})
7574
}
7675

7776
/**
7877
* Extract link and script, bind style scope
7978
* @param htmlStr html string
8079
* @param app app
8180
*/
82-
export function extractSourceDom (htmlStr: string, app: AppInterface): void {
81+
export function extractSourceDom(htmlStr: string, app: AppInterface): void {
8382
const wrapElement = app.parseHtmlString(htmlStr)
8483
const microAppHead = globalEnv.rawElementQuerySelector.call(wrapElement, 'micro-app-head')
8584
const microAppBody = globalEnv.rawElementQuerySelector.call(wrapElement, 'micro-app-body')
@@ -92,7 +91,7 @@ export function extractSourceDom (htmlStr: string, app: AppInterface): void {
9291

9392
const fiberStyleTasks: fiberTasks = app.isPrefetch || app.fiber ? [] : null
9493

95-
flatChildren(wrapElement, app, microAppHead, fiberStyleTasks)
94+
flatBodyChildren(wrapElement, app, fiberStyleTasks)
9695

9796
/**
9897
* Style and link are parallel, as it takes a lot of time for link to request resources. During this period, style processing can be performed to improve efficiency.

src/source/scripts.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,9 +531,16 @@ export function runScript (
531531
runParsedFunction(app, scriptInfo)
532532
}
533533
} catch (e) {
534-
console.error(`[micro-app from ${replaceElement ? 'runDynamicScript' : 'runScript'}] app ${app.name}: `, e, address)
534+
console.warn(`[micro-app from ${replaceElement ? 'runDynamicScript' : 'runScript'}] app ${app.name}: `, e, address)
535535
// throw error in with sandbox to parent app
536-
throw e
536+
const error = e as Error
537+
let throwError = true
538+
if (typeof microApp?.options?.excludeRunScriptFilter === 'function') {
539+
throwError = microApp.options.excludeRunScriptFilter(address, error, app.name, app.url) !== true
540+
}
541+
if (throwError) {
542+
throw e
543+
}
537544
}
538545
}
539546

typings/global.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ declare module '@micro-app/types' {
363363
fetch?: fetchType
364364
globalAssets?: globalAssetsType,
365365
excludeAssetFilter?: (assetUrl: string) => boolean
366+
excludeRunScriptFilter?: (scriptUrl: string, error: Error, appName: string, appUrl: string) => boolean
366367
/* image video audio 是否设置 crossOrigin = 'anonymous' */
367368
includeCrossOrigin?: (assetUrl: string) => boolean
368369
getRootElementParentNode?: (node: Node, appName: AppName) => void

0 commit comments

Comments
 (0)