umijs / qiankun

📦 🚀 Blazing fast, simple and complete solution for micro frontends.
https://qiankun.umijs.org
MIT License
15.71k stars 2k forks source link

styled-components CSSOM模式 应用切换样式丢失问题 #2603

Open Aeero opened 1 year ago

Aeero commented 1 year ago

What happens?

子应用使用了styled-components的CSSOM模式,切换到其他应用再切换回来,某些情况下会样式丢失

Mini Showcase Repository(REQUIRED)

https://github.com/Aeero/qiankun-issue/tree/bug/styled-components-cssom

How To Reproduce

正常case

step 1: yarn examples:install & yarn examples:start

step 2: 打开url: http://localhost:7099/react16-2

step 3: 页面上有一个红色的div image 此时动态生成的styled-components 样式节点 cssRules.length === 1 image

step 4: 点击"click me",页面上生成了一个绿色的div image 此时动态生成的styled-components 样式节点 cssRules.length === 2 image

异常case(step1 ~ 3 同上)

step 1: yarn examples:install & yarn examples:start

step 2: 打开url: http://localhost:7099/react16-2

step 3: 页面上有一个红色的div,此时动态生成的styled-components 样式节点 cssRules.length === 1

step 4: 切换到 url: http://localhost:7099/react16(点击左侧导航

step 5: 切换回 url: url: http://localhost:7099/react16-2(点击左侧导航

step 6: 点击“click me” 此时绿色div样式丢失(此时动态生成的styled-components 样式节点 cssRules.length依旧是1,也就是后续生成的新样式没有正确的插入到合适的位置)

image

问题定位

styled-components对CSSOM模式的处理方式 image

可以看到,其实并没有保存style节点的引用,保存的是 style.sheet

然后style.sheet有点不一样,当html里删除掉了某个style节点,该节点的sheet属性会自动被删除,即使重新添加,sheet的引用和之前的也不一样了

image

qiankun对子应用切换会删除style tag,然后rebuild时会重新append style tag,styled-components保存的sheet引用就丢失了,所以就导致新样式挂载失败

refs

https://github.com/umijs/qiankun/issues/617

Context

ToruKiyono commented 5 months ago

我也碰到过这个问题,初步怀疑是qiankun框架link挂载样式文件丢失导致的,具体原因没有继续往下定位了,但是有个解决方案,可以将link挂载的样式文件转为用style组装的方式,这样就不会丢失了。