Skip to content

Commit

Permalink
fix: fix bug for umdMode of global key & global listener
Browse files Browse the repository at this point in the history
  • Loading branch information
bailicangdu committed Jul 26, 2022
1 parent eca8ee5 commit bc5d864
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 74 deletions.
72 changes: 36 additions & 36 deletions dev/children/react16/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,48 +46,48 @@ window.addEventListener('appstate-change', function (e) {
})

/* ----------------------分割线-默认模式--------------------- */
ReactDOM.render(
<React.StrictMode>
<Router />
</React.StrictMode>,
document.getElementById('root')
);

// 监听卸载
window.addEventListener('unmount', function () {
ReactDOM.unmountComponentAtNode(document.getElementById('root'));
console.log('微应用react16卸载了 -- 自定义事件unmount');
})
// ReactDOM.render(
// <React.StrictMode>
// <Router />
// </React.StrictMode>,
// document.getElementById('root')
// );

// // 监听卸载
// window.addEventListener('unmount', function () {
// ReactDOM.unmountComponentAtNode(document.getElementById('root'));
// console.log('微应用react16卸载了 -- 自定义事件unmount');
// })

// console.timeEnd('react#16');

/* ----------------------分割线-umd模式--------------------- */
// function mount () {
// ReactDOM.render(
// <React.StrictMode>
// <Router />
// </React.StrictMode>,
// document.getElementById('root')
// );
// console.log('微应用react16渲染了 -- 来自umd-mount');
// console.timeEnd('react#16');
// }
function mount () {
ReactDOM.render(
<React.StrictMode>
<Router />
</React.StrictMode>,
document.getElementById('root')
);
console.log('微应用react16渲染了 -- 来自umd-mount');
console.timeEnd('react#16');
}

// function unmount () {
// console.log('微应用react16卸载了 -- 来自umd-unmount');
// // 卸载时关闭弹窗
// notification.destroy()
// // 卸载应用
// ReactDOM.unmountComponentAtNode(document.getElementById('root'));
// }
function unmount () {
console.log('微应用react16卸载了 -- 来自umd-unmount');
// 卸载时关闭弹窗
notification.destroy()
// 卸载应用
ReactDOM.unmountComponentAtNode(document.getElementById('root'));
}

// // 微前端环境下,注册mount和unmount方法
// if (window.__MICRO_APP_ENVIRONMENT__) {
// window[`micro-app-${window.__MICRO_APP_NAME__}`] = { mount, unmount }
// } else {
// // 非微前端环境直接渲染
// mount();
// }
// 微前端环境下,注册mount和unmount方法
if (window.__MICRO_APP_ENVIRONMENT__) {
window[`micro-app-${window.__MICRO_APP_NAME__}`] = { mount, unmount }
} else {
// 非微前端环境直接渲染
mount();
}


/* ---------------------- 全局事件 --------------------- */
Expand Down
31 changes: 30 additions & 1 deletion dev/children/react16/src/pages/page2/page2.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import {
Form,
Select,
Expand All @@ -19,6 +19,17 @@ import styled from 'styled-components'
import './page2.css'
import bigImg from '../../assets/big-img.jpeg';

// 测试umd二次渲染时全局变量是否丢失
window.umdGlobalKey = 'umdGlobalKey'

window.addEventListener('click', () => {
console.log('测试umd懒加载页面二次渲染全局事件')
})

window.microApp?.addDataListener((data) => {
console.log('懒加载的数据监听', data)
})

const StyledButton = styled.button`
background: transparent;
border-radius: 3px;
Expand Down Expand Up @@ -49,6 +60,7 @@ const normFile = (e) => {
};

const Page2 = () => {
const [count, changeCount] = useState(0)
const onFinish = (values) => {
console.log('Received values of form: ', values);
message.success('This is a success message');
Expand All @@ -60,11 +72,28 @@ const Page2 = () => {

useEffect(() => {
console.log('react16 page2 useEffect')
if (!window.umdGlobalKey) {
throw Error('umdGlobalKey missing')
}

const handler = (data) => {
console.log('懒加载组件内部的数据监听', data)
changeCount((pre) => {
return pre + 1
})
}

window.microApp?.addDataListener(handler)

return () => {
window.microApp?.removeDataListener(handler)
}
}, [])

return (
<div>
<img src={bigImg} alt="" width="100" />
<div>{count}</div>
<div>
<p>styled-component👇</p>
<StyledButton>按钮</StyledButton>
Expand Down
5 changes: 5 additions & 0 deletions dev/children/vue2/src/pages/page2.vue
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
</template>

<script>
// 测试umd二次渲染时全局变量是否丢失
window.umdGlobalKey = 'umdGlobalKey'
export default {
name: 'Page1',
Expand Down Expand Up @@ -111,6 +113,9 @@ export default {
},
mounted () {
console.log('vue2 page2 mounted')
if (!window.umdGlobalKey) {
alert('umdGlobalKey missing')
}
},
methods: {
submitForm(formName) {
Expand Down
12 changes: 0 additions & 12 deletions dev/main-react16/src/global.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,6 @@ microApp.start({
// console.log('vue2插件', url, options)
return code
}
},
{
loader (code) {
code = `
window.__micro_app_environment__ = window.__MICRO_APP_ENVIRONMENT__;
window.__micro_app_name__ = window.__MICRO_APP_NAME__;
window.__full_public_path__ = window.__MICRO_APP_PUBLIC_PATH__;
window.baseurl = window.__MICRO_APP_BASE_ROUTE__;
;${code}
`
return code
}
}
],
modules: {
Expand Down
1 change: 1 addition & 0 deletions docs/zh-cn/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- **Bug Fix**

- 🐞 修复了设置document.title, history.scrollRestoration时报`Illegal invocation`错误的问题。
- 🐞 修复了在umd模式部分场景下二次渲染时全局变量和全局事件丢失的问题。

- **Update**

Expand Down
7 changes: 6 additions & 1 deletion src/create_app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ export default class CreateApp implements AppInterface {
this.umdHookMount = mount as Func
this.umdHookUnmount = unmount as Func
this.umdMode = true
this.sandBox?.recordUmdSnapshot()
if (this.sandBox) this.sandBox.proxyWindow.__MICRO_APP_UMD_MODE__ = true
// this.sandBox?.recordUmdSnapshot()
try {
umdHookMountResult = this.umdHookMount()
} catch (e) {
Expand Down Expand Up @@ -315,13 +316,17 @@ export default class CreateApp implements AppInterface {
cloneContainer(this.container as Element, this.source.html as Element, false)
}

if (this.umdMode) {
this.sandBox?.recordUmdSnapshot()
}
/**
* this.container maybe contains micro-app element, stop sandbox should exec after cloneContainer
* NOTE:
* 1. if destroy is true, clear route state
* 2. umd mode and keep-alive will not clear EventSource
*/
this.sandBox?.stop(
this.umdMode,
this.keepRouteState && !destroy,
!this.umdMode || destroy,
)
Expand Down
13 changes: 10 additions & 3 deletions src/sandbox/effect.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { microAppWindowType } from '@micro-app/types'
import {
getCurrentAppName,
setCurrentAppName,
logWarn,
isFunction,
isBoundFunction,
Expand Down Expand Up @@ -234,6 +233,14 @@ export default function effect (appName: string, microAppWindow: microAppWindowT
let umdTimeoutIdMap = new Map<number, timeInfo>()
let umdOnClickHandler: unknown

const clearUmdSnapshotData = () => {
umdWindowListenerMap.clear()
umdIntervalIdMap.clear()
umdTimeoutIdMap.clear()
umdDocumentListenerMap.clear()
umdOnClickHandler = null
}

// record event and timer before exec umdMountHook
const recordUmdEffect = () => {
// record window event
Expand Down Expand Up @@ -288,13 +295,13 @@ export default function effect (appName: string, microAppWindow: microAppWindowT
umdOnClickHandler && documentClickListMap.set(appName, umdOnClickHandler)

// rebuild document event
setCurrentAppName(appName)
umdDocumentListenerMap.forEach((listenerList, type) => {
for (const listener of listenerList) {
document.addEventListener(type, listener, listener?.__MICRO_APP_MARK_OPTIONS__)
}
})
setCurrentAppName(null)

clearUmdSnapshotData()
}

// release all event listener & interval & timeout when unmount app
Expand Down
41 changes: 22 additions & 19 deletions src/sandbox/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export default class SandBox implements SandBoxInterface {
// Properties escape to rawWindow, cleared when unmount
private escapeKeys = new Set<PropertyKey>()
// record injected values before the first execution of umdHookMount and rebuild before remount umd app
private recordUmdInjectedValues?: Map<PropertyKey, unknown>
// private recordUmdInjectedValues?: Map<PropertyKey, unknown>
// sandbox state
private active = false
public proxyWindow: proxyWindow // Proxy
Expand Down Expand Up @@ -153,7 +153,7 @@ export default class SandBox implements SandBoxInterface {
}
}

public stop (keepRouteState: boolean, clearEventSource: boolean): void {
public stop (umdMode: boolean, keepRouteState: boolean, clearEventSource: boolean): void {
if (this.active) {
this.releaseEffect()
this.microAppWindow.microApp.clearDataListener()
Expand All @@ -173,16 +173,19 @@ export default class SandBox implements SandBoxInterface {
* NOTE:
* 1. injectedKeys and escapeKeys must be placed at the back
* 2. if key in initial microAppWindow, and then rewrite, this key will be delete from microAppWindow when stop, and lost when restart
* 3. umd mode will not delete global keys
*/
this.injectedKeys.forEach((key: PropertyKey) => {
Reflect.deleteProperty(this.microAppWindow, key)
})
this.injectedKeys.clear()

this.escapeKeys.forEach((key: PropertyKey) => {
Reflect.deleteProperty(globalEnv.rawWindow, key)
})
this.escapeKeys.clear()
if (!umdMode) {
this.injectedKeys.forEach((key: PropertyKey) => {
Reflect.deleteProperty(this.microAppWindow, key)
})
this.injectedKeys.clear()

this.escapeKeys.forEach((key: PropertyKey) => {
Reflect.deleteProperty(globalEnv.rawWindow, key)
})
this.escapeKeys.clear()
}

if (--SandBox.activeCount === 0) {
releaseEffectDocumentEvent()
Expand All @@ -196,21 +199,21 @@ export default class SandBox implements SandBoxInterface {

// record umd snapshot before the first execution of umdHookMount
public recordUmdSnapshot (): void {
this.microAppWindow.__MICRO_APP_UMD_MODE__ = true
// this.microAppWindow.__MICRO_APP_UMD_MODE__ = true
this.recordUmdEffect()
recordDataCenterSnapshot(this.microAppWindow.microApp)

this.recordUmdInjectedValues = new Map<PropertyKey, unknown>()
this.injectedKeys.forEach((key: PropertyKey) => {
this.recordUmdInjectedValues!.set(key, Reflect.get(this.microAppWindow, key))
})
// this.recordUmdInjectedValues = new Map<PropertyKey, unknown>()
// this.injectedKeys.forEach((key: PropertyKey) => {
// this.recordUmdInjectedValues!.set(key, Reflect.get(this.microAppWindow, key))
// })
}

// rebuild umd snapshot before remount umd app
public rebuildUmdSnapshot (): void {
this.recordUmdInjectedValues!.forEach((value: unknown, key: PropertyKey) => {
Reflect.set(this.proxyWindow, key, value)
})
// this.recordUmdInjectedValues!.forEach((value: unknown, key: PropertyKey) => {
// Reflect.set(this.proxyWindow, key, value)
// })
this.rebuildUmdEffect()
rebuildDataCenterSnapshot(this.microAppWindow.microApp)
}
Expand Down
2 changes: 1 addition & 1 deletion src/source/scripts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ export function runDynamicRemoteScript (
} catch (e) {
console.error(`[micro-app from runDynamicScript] app ${app.name}: `, e, url)
}
!info.module && dispatchOnLoadEvent(originScript)
!info.module && dispatchScriptOnLoadEvent()
}).catch((err) => {
logError(err, app.name)
dispatchOnErrorEvent(originScript)
Expand Down
6 changes: 5 additions & 1 deletion typings/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ declare module '@micro-app/types' {
useMemoryRouter: boolean,
defaultPage: string,
): void
stop (keepRouteState: boolean, clearEventSource: boolean): void
stop (
umdMode: boolean,
keepRouteState: boolean,
clearEventSource: boolean,
): void
// record umd snapshot before the first execution of umdHookMount
recordUmdSnapshot (): void
// rebuild umd snapshot before remount umd app
Expand Down

0 comments on commit bc5d864

Please sign in to comment.