Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] createBrowserHistory 无法透传 opts,导致在 qiankun 场景下 history 的全局监听事件无法移除 #12484

Open
asyncguo opened this issue Jun 20, 2024 · 3 comments

Comments

@asyncguo
Copy link

What happens?

qiankun 场景下,多个子应用切换时到会导致 window.addEventListener(popstate) 无法移除,导致内存溢出。

主要原因是:umi 通过 createHistory 生成路由时(history.tpl),history 模式会执行 createBrowserHistory ,而 createBrowserHistory 未接受传入的 opts,导致 history 在初始化路由时,window 值取了默认值 document.defaultView(createBrowserHistory)。

这种情况在 qiankun 场景下,createBrowserHistory 获取 document.defaultView 时触发沙箱逃逸(qiankun 内部主子应用会共享 document),实际取值为主应用的 window 对象,从而导致多个子应用的监听都会订阅到主应用上,即使子应用卸载后,事件监听还会存在,来回切换子应用时会不停的在主应用上累计监听,导致子应用会内存泄漏。

umi 临时文件 .umi/core/history.ts

export function createHistory(opts: any) {
  let h;
  if (opts.type === 'hash') {
    h = createHashHistory();
  } else if (opts.type === 'memory') {
    h = createMemoryHistory(opts);
  } else {
   // 期望透传 opts 给 history 的 createBrowserHistory
    h = createBrowserHistory();
  }
  if (opts.basename) {
    basename = opts.basename;
  }

// ...

  return h;
}

historycreateBrowserHistory 源码:

// remix-run/history
export function createBrowserHistory(
  options: BrowserHistoryOptions = {}
): BrowserHistory {
  let { window = document.defaultView! } = options;
  let globalHistory = window.history;

  // ...
  window.addEventListener(PopStateEventType, handlePop);
  // ...
}

期望解法:createBrowserHistory 可以接收 opts 参数,让用户传递子应用代理后的 window 参数(qiankun 内部会对 addEventListener 打补丁,可以保证子应用卸载时移除事件订阅)。

Context

  • Umi Version: 4.2.5
  • Node Version: 20
  • Platform: Mac OS
@asyncguo asyncguo changed the title [Bug] createBrowserHistory 无法透传 opts,导致在 qiankun 场景下全局监听事件无法移除 [Bug] createBrowserHistory 无法透传 opts,导致在 qiankun 场景下 history 的全局监听事件无法移除 Jun 20, 2024
@fz6m
Copy link
Member

fz6m commented Jun 22, 2024

可以估计多少次切换子应用后会导致页面崩溃吗,因为内存泄漏很容易在各种代码里发生,在一定程度上是可以容许泄露的,但这确实是一个问题。

@asyncguo
Copy link
Author

可以估计多少次切换子应用后会导致页面崩溃吗,因为内存泄漏很容易在各种代码里发生,在一定程度上是可以容许泄露的,但这确实是一个问题。

页面崩溃的case比较难测,除了history的监听泄漏,qiankun 沙箱还存在其他场景下的泄漏比如:深度对象的代理修改会触发沙箱逃逸,也会存在一定的内存泄漏。
目前 history 的问题主要是因为 createBrowserHistory 时没有接收 opts 参数,不知道是否可以支持用户手动传入的参数,比如: window。

@fz6m
Copy link
Member

fz6m commented Jun 26, 2024

我认为如果此问题不解决,最多只是一定程度的内存泄漏,但并没有人发生应用的崩溃,因为很多应用都存在内存泄露,在一定程度是允许的,所以这个问题不是致命的。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants