使用了qiankun之后为什么主应用在浏览器后退时会把子应用的访问前缀/archives截掉导致404

3 阅读1分钟

这是 qiankun + Vue Router 4 的一个已知冲突,根因在于两个 Vue Router 实例共享同一个 window.history,但各自的 base 不同。

Vue Router 4 的 history.state 机制Vue Router 4 每次导航时,会调用 history.pushState / history.replaceState

在 history.state 里存三个字段:

history.state = {
back: '/contracts', // 上一个路径
current: '/company-cert/business-license', // 当前路径
forward: null
}

关键点:这些路径是相对于 router 自己的 base 的。子应用 router 的 base 是 /archives,所以它存的是去掉 /archives 后的相对路径。


浏览器后退时发生了什么

  1. 用户在 /archives/company-cert/business-license 页面,点击浏览器后退

  2. 浏览器触发 popstate 事件

  3. 两个 router 同时监听到这个事件:

  • 子应用 router(base = /archives):正确理解 state.back = '/contracts' 意思是 /archives/contracts

  • 基座 router(base = /):也读到 state.back = '/contracts',但它认为这就是绝对路径 /contracts

  1. 基座 router 抢先处理,把 URL 导航到 /contracts

  2. /contracts 在基座里没有对应路由 → 404


为什么没有子应用时不会出现?只有一个 Vue Router 实例时:

  • 只有一个 router 读写 history.state
  • 只有一个 base,路径的存和取是一致的
  • 不存在"另一个 router 用不同的 base 来解读同一份 state"的问题

一句话总结:两个 router 共享一个 history.state,子应用写进去的是去掉 /archives 前缀的相对路径,基座读出来时当成了绝对路径,前缀就丢了。这是 Vue Router 4 + qiankun 的架构性冲突,所以才需要在基座的 beforeEach 里手动检测并补回前缀。