umijs / umi

A framework in react community ✨
https://umijs.org
MIT License
15.3k stars 2.65k forks source link

【Bug】MicroApp 在更新子应用时缺少 __globalRoutesInfo #12306

Closed purple-force closed 4 months ago

purple-force commented 5 months ago

MicroApp 在更新子应用时, props 缺少 __globalRoutesInfo,导致子应用 MicroAppLink 取不到值。

另外,urlFactory,只通过 app.path.replace('/*', '')并不能获得正确的地址,比如 app.path为 带有占位符的情况 /org/:orgId/task/*。 目前项目中只能通过原生的 window.history.pushState 进行子应用间的跳转。

fz6m commented 5 months ago
  1. 详细的介绍一下你遇到的问题吧,提供一个最小复现。

  2. 如果想在子应用之间跳转的话,子应用使用的是自己的路由,不能跳到其他应用的路由去吧,所以应用间跳转,我理解就两个常用方案:

    i. 把主应用的统一跳转方法传给子应用使用,然后想跳转哪里就跳哪里。

    ii. 用和应用路由无关的原生路由方法,比如 window.history.pushState

purple-force commented 5 months ago
  1. 详细的介绍一下你遇到的问题吧,提供一个最小复现。
  2. 如果想在子应用之间跳转的话,子应用使用的是自己的路由,不能跳到其他应用的路由去吧,所以应用间跳转,我理解就两个常用方案: i. 把主应用的统一跳转方法传给子应用使用,然后想跳转哪里就跳哪里。 ii. 用和应用路由无关的原生路由方法,比如 window.history.pushState

https://umijs.org/docs/max/micro-frontend#%E5%AD%90%E5%BA%94%E7%94%A8%E4%B9%8B%E9%97%B4%E8%B7%B3%E8%BD%AC

文档中子应用之间跳转,使用的 MicroAppLink。

复现 demo,https://github.com/purple-force/umi-micro-app-link

  1. 启动3个工程。
  2. 访问子应用 1,http://localhost:3000/123/app1
  3. 点击跳转到子应用2的链接,可以发现链接是错的。原因如 issue 描述。
fz6m commented 4 months ago

我看了下。

MicroAppLink 可以在子应用里跳转另一个子应用,但它依赖了 umi 的 model 数据流插件,才能在内部把主应用的数据自动传递给子应用,从而子应用才知道一共有哪些子应用,这样才能知道跳转到哪,如果不开启 model 插件,是没法用 MicroAppLink 的。

如果要用 MicroAppLink ,需要给每个应用都开启 model: {}

参考以上的说明,如果只是普通的路径(不带 :id 这种参数),是没问题的,但你写的这种路由路径比较特殊,子应用是不知道当前父应用路由里的 params 是多少的,它只能跳到 /:id/app2 去,所以如果你硬要用 MicroAppLink ,得自己 fork copy 一份 src/.umi/plugin-qiankun-slave/MicroAppLink.tsx 这个里面的代码,自己改一下里面处理 url 的逻辑,把动态参数替换掉(当然还要自己做一下父应用到子应用 params 传递这个功能,才能替换掉里面的 :id )。

但这样其实比较麻烦,因为 MicroAppLink 这里面的代码非常少,最后也只是调用了 window.history.pushState ,现在更多人都是直接用 window.history.pushState 去做跳转的,因为你拼出来想要的 url 就可以了,和 MicroAppLink 的区别就是 MicroAppLink 还帮你兼容了不同路由类型(如 hash 路由),并且帮你寻找了其他应用的路由表信息(从而你可以直接写那个应用的名字),所以如果你的使用范围比较限定,就是普通的路由,而且路径也比较简单,没必要使用 MicroAppLink (特别是你的路径里有动态参数这种情况,MicroAppLink 是做不到替换参数的) 。

purple-force commented 4 months ago

我看了下。

MicroAppLink 可以在子应用里跳转另一个子应用,但它依赖了 umi 的 model 数据流插件,才能在内部把主应用的数据自动传递给子应用,从而子应用才知道一共有哪些子应用,这样才能知道跳转到哪,如果不开启 model 插件,是没法用 MicroAppLink 的。

如果要用 MicroAppLink ,需要给每个应用都开启 model: {}

参考以上的说明,如果只是普通的路径(不带 :id 这种参数),是没问题的,但你写的这种路由路径比较特殊,子应用是不知道当前父应用路由里的 params 是多少的,它只能跳到 /:id/app2 去,所以如果你硬要用 MicroAppLink ,得自己 fork copy 一份 src/.umi/plugin-qiankun-slave/MicroAppLink.tsx 这个里面的代码,自己改一下里面处理 url 的逻辑,把动态参数替换掉(当然还要自己做一下父应用到子应用 params 传递这个功能,才能替换掉里面的 :id )。

但这样其实比较麻烦,因为 MicroAppLink 这里面的代码非常少,最后也只是调用了 window.history.pushState ,现在更多人都是直接用 window.history.pushState 去做跳转的,因为你拼出来想要的 url 就可以了,和 MicroAppLink 的区别就是 MicroAppLink 还帮你兼容了不同路由类型(如 hash 路由),并且帮你寻找了其他应用的路由表信息(从而你可以直接写那个应用的名字),所以如果你的使用范围比较限定,就是普通的路由,而且路径也比较简单,没必要使用 MicroAppLink (特别是你的路径里有动态参数这种情况,MicroAppLink 是做不到替换参数的) 。

重新调整了下,每个应用开启了 model。 同时在主应用里使用了 getInitialState,并将 initialState 通过 useQiankunStateForSlave 给子应用消费。在主应用 Layout 里调用 setInitialState 进行更新,进而触发子应用的更新,这时传给子应用的 props 缺少 globalRoutesInfo,导致路由类型都不对了。 路径参数的情形不支持是可以的。globalRoutesInfo 在子应用更新时缺失我觉得插件层面是要处理下的。

fz6m commented 4 months ago

你这里指的是子应用套壳开发时的热更新吗,如有问题,需要给一个最小复现。

purple-force commented 4 months ago

你这里指的是子应用套壳开发时的热更新吗,如有问题,需要给一个最小复现。

不是热更新,在主应用 Layout 里调用 setInitialState,进而会触发子应用的rerender。最新代码已经上传了,还是这个代码库。