We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
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
我是直接查看的源码,发现了patchHTMLDynamicAppendPrototypeFunctions这个函数的代码逻辑有些问题。(所以就没有提供最小可复现仓库了,因为直接用的官方demo,打断点调试就行。)
这个函数的逻辑,我简化一下并且只看appendChild方法,方便观察:
function patchHTMLDynamicAppendPrototypeFunctions(isInvokedByMicroApp, containerConfigGetter) { const rawHeadAppendChild = HTMLHeadElement.prototype.appendChild; if (rawHeadAppendChild[overwrittenSymbol] !== true) { function appendChildNew() { // 使用rawHeadAppendChild, isInvokedByMicroApp, containerConfigGetter } appendChildNew[overwrittenSymbol] = true; HTMLHeadElement.prototype.appendChild = appendChildNew; } return function unpatch() { // 当应用全部unmount时,会调用 HTMLHeadElement.prototype.appendChild = rawHeadAppendChild; } }
分析一下:
rawXXX
覆盖标志
unpatch()
这里面存在两个问题:
只要有2个以上的子应用加载过,原生append就找不回来了。unpatch()函数也没有任何作用。
新append只会在首次加载时,创建一次。
所以这个函数内用到的isInvokedByMicroApp和containerConfigGetter就是第一个子应用在调用patchHTMLDynamicAppendPrototypeFunctions时提供的,并且不再改变。
isInvokedByMicroApp
containerConfigGetter
patchHTMLDynamicAppendPrototypeFunctions
对于LooseSandbox这个问题很严重。因为它提供的isInvokedByMicroApp和containerConfigGetter都是从函数作用域内取的参数。
function patchLooseSandbox(appName: string, /* ... */) { const unpatchDynamicAppendPrototypeFunctions = patchHTMLDynamicAppendPrototypeFunctions( // 注意这个appName是从函数参数取到的 () => checkActivityFunctions(window.location).some((name) => name === appName), () => ({ appName, /* ... */ }), ); }
假如第一个加载的子应用名叫vue-app,它调用patchHTMLDynamicAppendPrototypeFunctions,将原型append设置为新append。新append内部使用的isInvokedByMicroApp参数由vue-app提供。因此这个appName将会永远都是vue-app。
不管当前是哪个应用处于激活状态,只要这个应用内调用了appendChild方法,就会拿当前window.location和vue-app进行比较。可想而知,答案是错的。
window.location
感谢qiankun的技术大佬,我已经尽量把问题写的很清晰。如果有什么错误,请及时指正。如果我提的问题确实存在,辛苦尽快调整~
The text was updated successfully, but these errors were encountered:
同问,在内存的时候发现了类似的问题
Sorry, something went wrong.
No branches or pull requests
问题描述
我是直接查看的源码,发现了patchHTMLDynamicAppendPrototypeFunctions这个函数的代码逻辑有些问题。(所以就没有提供最小可复现仓库了,因为直接用的官方demo,打断点调试就行。)
这个函数的逻辑,我简化一下并且只看appendChild方法,方便观察:
分析一下:
rawXXX
对象存储原生append。随后head的原型append被设置为新append。并且新append的覆盖标志
设为true。rawXXX
对象变为新append。由于新append的覆盖标志
为true,所以跳过if。unpatch()
。此时会将原型append设置为新append(等于没变)。这里面存在两个问题:
只要有2个以上的子应用加载过,原生append就找不回来了。
unpatch()
函数也没有任何作用。新append只会在首次加载时,创建一次。
所以这个函数内用到的
isInvokedByMicroApp
和containerConfigGetter
就是第一个子应用在调用patchHTMLDynamicAppendPrototypeFunctions
时提供的,并且不再改变。对于LooseSandbox这个问题很严重。因为它提供的
isInvokedByMicroApp
和containerConfigGetter
都是从函数作用域内取的参数。假如第一个加载的子应用名叫vue-app,它调用
patchHTMLDynamicAppendPrototypeFunctions
,将原型append设置为新append。新append内部使用的isInvokedByMicroApp
参数由vue-app提供。因此这个appName将会永远都是vue-app。不管当前是哪个应用处于激活状态,只要这个应用内调用了appendChild方法,就会拿当前
window.location
和vue-app进行比较。可想而知,答案是错的。致谢
感谢qiankun的技术大佬,我已经尽量把问题写的很清晰。如果有什么错误,请及时指正。如果我提的问题确实存在,辛苦尽快调整~
相关环境信息
The text was updated successfully, but these errors were encountered: