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

fix(qiankun): 尝试修复嵌入主应用的子应用的热更新问题 #629

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

fxxjdedd
Copy link

@fxxjdedd fxxjdedd commented Jun 7, 2021

当前问题在于, 在 #418 中, 将clientRenderOpts改为clientRenderOptsStack, 并以pop的方式获取, 这样有两个问题:

  1. 当热更新时, 由于已经pop过, 此时clientRenderOptsStack为空, 那么src中生成的 .umi/umi.ts 的modifyClientRenderOpts操作将无法修改rootElement为dom, 而是保持为string.
    这就导致热更新时, 直接把子应用挂载到了string类型的rootElement对应的dom上, 也就是最外层的那个root, 就相当于子应用把主应用覆盖了.

  2. #423 讲到, mount顺序是一定的, 但是render不是. 又因为上述pop过程是在render过程中进行的, 那么这个pop的顺序也不一定是安全的.
    这里使用appId的方式来保证render和clientRenderOpts的一致性.

futengda added 2 commits June 7, 2021 18:28
当前问题在于, 在 [umijs#418](umijs#418) 中, 将clientRenderOpts改为clientRenderOptsStack, 并以pop的方式获取, 这样有两个问题:

1. 当热更新时, 由于已经pop过, 此时clientRenderOptsStack为空, 那么src中生成的`.umi/umi.ts`的modifyClientRenderOpts操作将无法修改rootElement为dom, 而是保持为string.
   这就导致热更新时, 直接把子应用挂载到了string类型的rootElement对应的dom上, 也就是最外层的那个root, 就相当于子应用把主应用覆盖了.

2. 在 [umijs#423](umijs#423) 讲到, mount顺序是一定的, 但是render不是. 又因为上述pop过程是在render过程中进行的, 那么这个pop的顺序也不一定是安全的.
   这里使用appId的方式来保证render和clientRenderOpts的一致性.
@fxxjdedd
Copy link
Author

fxxjdedd commented Jun 7, 2021

需要配合 umijs/umi#6702, 必须先等这个合并。

futengda added 3 commits June 7, 2021 19:19
如果umijs没有升级到这次提交[#6702](umijs/umi#6702), 则使用原来的处理方式
@fxxjdedd fxxjdedd changed the title 尝试修复嵌入主应用的子应用的热更新问题 fix(qiankun): 尝试修复嵌入主应用的子应用的热更新问题 Jun 8, 2021
@fxxjdedd
Copy link
Author

fxxjdedd commented Jun 8, 2021

related issues:

umijs/qiankun#395
umijs/qiankun#340

@fxxjdedd
Copy link
Author

fxxjdedd commented Jun 8, 2021

当前pr还在进行中,过程如下:

  1. 一开始发现主应用里嵌入子应用,子应用热更新,会导致src/.umi/umi.ts的热更新流程挂掉,于是提交了当前pr和feat: allow entryCodeAhead block to modify pluginArgs umi#6702 用于解决。

  2. 接着又发现,umi项目中如果开启了fastRefresh,其实有两套热更新:

    1. 基于src/.umi/umi.ts的全量更新,相当于重新调用ReactDOM.render,这不是完美的,会丢失页面状态。它应该仅仅在路由变化时触发。
    2. 基于fastRefresh的局部更新,使用react提供的react-refresh包完成,会尽可能保留页面状态,趋于完美。
  3. 于是又发现了两个新问题:

    1. src/.umi/umi.ts异常触发的问题,只要我们导出的组件使用HOC包裹(不管HOC干了啥),都会导致一次全量更新,导致页面状态异常丢失。
    2. 嵌入到主应用的子应用的fastRefresh是挂掉的,如果没能触发src/.umi/umi.ts中的全量更新,页面将不会更新
  4. 我们还需要做什么来修复这两个新问题

    1. 修复src/.umi/umi.ts异常触发的问题,因为只要这个问题存在,即使fastRefresh修复了,也会导致全量更新覆盖掉局部更新。这个问题还在解决中。
    2. 修复子应用的fastRefresh挂掉的问题,问题出在fastRefresh会根据window对象上的__reactRefreshInjected来判断是否注入必要的内容,见ReactRefreshEntry ,如果主应用和子应用都开启了fastRefresh,那么当子应用的fastRefresh进行__reactRefreshInjected判断时,由于子应用继承了主应用的window内容,就没能进行注入。
  5. 当前进展

    1. 异常触发问题:这个问题仅出现在umi router的根组件(仅包含在.umirc.ts中的routes中定义的那些组件),当这个组件是以HOC的形式导出时,就会触发src/.umi/umi.ts中的全量热更新。没什么好办法,只能在用户侧控制,比如qiankun中尽量不要用connectMaster而是用useModel("@@qiankunStateFromMaster")
    2. 子应用fastRefresh问题: feat: add variableGetterWhiteList to not inherit properties from rawWindow qiankun#1495

@fxxjdedd fxxjdedd changed the title fix(qiankun): 尝试修复嵌入主应用的子应用的热更新问题 WIP: fix(qiankun): 尝试修复嵌入主应用的子应用的热更新问题 Jun 8, 2021
@fxxjdedd
Copy link
Author

fxxjdedd commented Jun 9, 2021

应该没什么要改的了

@kuitos 能帮忙审查一下吗?

@fxxjdedd fxxjdedd changed the title WIP: fix(qiankun): 尝试修复嵌入主应用的子应用的热更新问题 fix(qiankun): 尝试修复嵌入主应用的子应用的热更新问题 Jun 9, 2021
@fxxjdedd
Copy link
Author

fxxjdedd commented Jun 9, 2021

fixed umijs/umi#6521

@junhui75165
Copy link

请问更新了吗

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

Successfully merging this pull request may close these issues.

None yet

2 participants