diff --git a/dev/children/react16/src/index.js b/dev/children/react16/src/index.js
index c754c8e8b..7d9ca3d21 100644
--- a/dev/children/react16/src/index.js
+++ b/dev/children/react16/src/index.js
@@ -10,9 +10,9 @@ import { Modal, notification } from 'antd';
import subMicroApp from '@micro-zoe/micro-app'
// 循环内嵌
-subMicroApp.start({
- tagName: 'micro-app-sub'
-})
+// subMicroApp.start({
+// tagName: 'micro-app-sub'
+// })
// 数据监听
window.microApp?.addDataListener((data) => {
diff --git a/dev/children/react16/src/pages/inline/inline.js b/dev/children/react16/src/pages/inline/inline.js
index b66a3000f..d443cfb42 100644
--- a/dev/children/react16/src/pages/inline/inline.js
+++ b/dev/children/react16/src/pages/inline/inline.js
@@ -25,7 +25,7 @@ function Vue2 () {
{
showLoading &&
}
- ()
@@ -32,6 +33,7 @@ export interface CreateAppParam {
name: string
url: string
ssrUrl?: string
+ sandboxType?: string
scopecss: boolean
useSandbox: boolean
inline?: boolean
@@ -53,6 +55,7 @@ export default class CreateApp implements AppInterface {
name: string
url: string
ssrUrl: string
+ sandboxType: string
container: HTMLElement | ShadowRoot | null = null
inline: boolean
scopecss: boolean
@@ -69,6 +72,7 @@ export default class CreateApp implements AppInterface {
inline,
scopecss,
useSandbox,
+ sandboxType,
baseroute,
}: CreateAppParam) {
this.container = container ?? null
@@ -86,6 +90,7 @@ export default class CreateApp implements AppInterface {
}
this.loadSourceCode()
this.useSandbox && (this.sandBox = new SandBox(name, url))
+ this.sandboxType = sandboxType ?? 'default'
}
// Load resources
@@ -161,6 +166,15 @@ export default class CreateApp implements AppInterface {
cloneContainer(this.source.html as Element, this.container as Element, !this.umdMode)
+ // 初始化 iframe
+ if (this.sandboxType === 'iframe') {
+ const iframeId = `micro-app-iframe-${this.name}`
+ const iframe = createIframe(`micro-app-iframe-${this.name}`)
+ // @ts-ignore
+ window[iframeId] = iframe
+ this.container?.querySelector('micro-app-body')?.appendChild(iframe)
+ }
+
this.sandBox?.start(this.baseroute)
let umdHookMountResult: any // result of mount function
diff --git a/src/iframe/create.ts b/src/iframe/create.ts
new file mode 100644
index 000000000..86a54edb1
--- /dev/null
+++ b/src/iframe/create.ts
@@ -0,0 +1,8 @@
+export const createIframe = (iframeId: string) => {
+ const iframe = document.createElement('iframe')
+ iframe.src = 'about:blank'
+ iframe.id = iframeId
+ iframe.style.display = 'none'
+
+ return iframe
+}
diff --git a/src/iframe/run.ts b/src/iframe/run.ts
new file mode 100644
index 000000000..ca9689c35
--- /dev/null
+++ b/src/iframe/run.ts
@@ -0,0 +1,11 @@
+import { pureCreateElement } from '../libs/utils'
+
+export const runCodeToIframe = (iframe: HTMLIFrameElement, proxyWindow:Window | undefined, code:string) => {
+ const iframeDoc = iframe.contentWindow?.document
+
+ iframe.contentWindow && ((iframe.contentWindow as any).window.__MICRO_APP_PROXY_WINDOW__ = proxyWindow)
+
+ const script = pureCreateElement('script')
+ script.textContent = code
+ iframeDoc?.body.appendChild(script)
+}
diff --git a/src/micro_app_element.ts b/src/micro_app_element.ts
index bcc4c0e3f..6a958fe8a 100644
--- a/src/micro_app_element.ts
+++ b/src/micro_app_element.ts
@@ -309,6 +309,7 @@ export function defineElement (tagName: string): void {
inline: this.getDisposeResult('inline'),
scopecss: !(this.getDisposeResult('disableScopecss') || this.getDisposeResult('shadowDOM')),
useSandbox: !this.getDisposeResult('disableSandbox'),
+ sandboxType: this.getAttribute('sandboxType') || 'default',
baseroute: this.getBaseRouteCompatible(),
})
diff --git a/src/sandbox/index.ts b/src/sandbox/index.ts
index 40e229401..ac2f2a9d9 100644
--- a/src/sandbox/index.ts
+++ b/src/sandbox/index.ts
@@ -349,7 +349,7 @@ export default class SandBox implements SandBoxInterface {
// set hijack Properties to microAppWindow
private setHijackProperties (microAppWindow: microAppWindowType, appName: string): void {
- let modifiedEval: unknown, modifiedImage: unknown
+ let modifiedImage: unknown
rawDefineProperties(microAppWindow, {
document: {
get () {
@@ -359,16 +359,12 @@ export default class SandBox implements SandBoxInterface {
configurable: false,
enumerable: true,
},
- eval: {
+ location: {
get () {
- throttleDeferForSetAppName(appName)
- return modifiedEval || eval
- },
- set: (value) => {
- modifiedEval = value
+ return globalEnv.rawWindow.location
},
- configurable: true,
- enumerable: false,
+ configurable: false,
+ enumerable: true,
},
Image: {
get () {
diff --git a/src/source/scripts.ts b/src/source/scripts.ts
index fea3cdfd6..0f542dc7b 100644
--- a/src/source/scripts.ts
+++ b/src/source/scripts.ts
@@ -25,6 +25,7 @@ import {
import microApp from '../micro_app'
import globalEnv from '../libs/global_env'
import { globalKeyToBeCached } from '../constants'
+import { runCodeToIframe } from '../iframe/run'
type moduleCallBack = Func & { moduleCount?: number, errorCount?: number }
@@ -287,7 +288,7 @@ export function runScript (
// TEST IGNORE
app.container?.querySelector('micro-app-body')!.appendChild(scriptElement)
} else {
- runCode2Function(code, info)
+ runCode2Function(code, info, app)
if (isDynamic) return document.createComment('dynamic script extract by micro-app')
}
} catch (e) {
@@ -341,7 +342,7 @@ export function runDynamicRemoteScript (
if (app.inline || info.module) {
runCode2InlineScript(url, code, info.module, replaceElement as HTMLScriptElement, dispatchScriptOnLoadEvent)
} else {
- runCode2Function(code, info)
+ runCode2Function(code, info, app)
}
} catch (e) {
console.error(`[micro-app from runDynamicScript] app ${app.name}: `, e, url)
@@ -389,10 +390,22 @@ function runCode2InlineScript (
}
// init & run code2Function
-function runCode2Function (code: string, info: sourceScriptInfo) {
+function runCode2Function (
+ code: string,
+ info: sourceScriptInfo,
+ app: AppInterface
+) {
+ if (app.sandboxType === 'iframe') {
+ const iframeId = `micro-app-iframe-${app.name}`
+ const iframe = document.getElementById(iframeId) as HTMLIFrameElement
+ runCodeToIframe(iframe, app?.sandBox?.proxyWindow, code)
+ return
+ }
+
if (!info.code2Function) {
info.code2Function = new Function(code)
}
+
info.code2Function.call(window)
}
@@ -415,12 +428,30 @@ function bindScope (
if (app.sandBox && !info.module) {
globalEnv.rawWindow.__MICRO_APP_PROXY_WINDOW__ = app.sandBox.proxyWindow
- return `;(function(proxyWindow){with(proxyWindow.__MICRO_APP_WINDOW__){(function(${globalKeyToBeCached}){;${code}\n}).call(proxyWindow,${globalKeyToBeCached})}})(window.__MICRO_APP_PROXY_WINDOW__);`
+ return app.sandboxType === 'iframe'
+ ? createIfameSandboxJSCode(code)
+ : `;(function(proxyWindow){with(proxyWindow.__MICRO_APP_WINDOW__){(function(${globalKeyToBeCached}){;${code}\n}).call(proxyWindow,${globalKeyToBeCached})}})(window.__MICRO_APP_PROXY_WINDOW__);`
}
return code
}
+const createWithStatement = (code: string) => `with(window.__MICRO_APP_WINDOW__){${code}}`
+
+export const createIfameSandboxJSCode = (code: string): string => {
+ return `(function(window, self, global,globalThis,${globalKeyToBeCached}) {
+ // Angular 特殊处理
+ var Zone = window.Zone;
+ ${createWithStatement(code)}
+}).bind(window.__MICRO_APP_PROXY_WINDOW__)(
+ window.__MICRO_APP_PROXY_WINDOW__,
+ window.__MICRO_APP_PROXY_WINDOW__,
+ window.__MICRO_APP_PROXY_WINDOW__,
+ window.__MICRO_APP_PROXY_WINDOW__,
+ ${globalKeyToBeCached}
+);`
+}
+
/**
* Call the plugin to process the file
* @param url script address
diff --git a/typings/global.d.ts b/typings/global.d.ts
index 2873e6b13..71c7c393d 100644
--- a/typings/global.d.ts
+++ b/typings/global.d.ts
@@ -53,6 +53,7 @@ declare module '@micro-app/types' {
baseroute: string // route prefix, default is ''
source: sourceType // sources of css, js, html
sandBox: SandBoxInterface | null // sandbox
+ sandboxType: string;
umdMode: boolean // is umd mode
// Load resources