微前端中History模式的路由拦截和传统前端路由拦截有什么区别?

微前端中 History 模式的路由拦截,和传统单应用前端路由拦截(比如 Vue Router 的 beforeEach、React Router 的 useNavigate 拦截)在核心目标、实现逻辑、处理范围等方面的本质区别,我会从「本质定位→核心维度对比→实战案例→关键总结」层层拆解,结合你熟悉的 Vue/Wujie 场景让差异一目了然。

一、先厘清:两者的核心本质定位

1. 传统前端路由拦截(单应用)

单应用内部的 “路由管控”:拦截自身应用的路由跳转(如 /proOrder/home),目的是在跳转前 / 后做 “应用内逻辑处理”(鉴权、页面标题修改、加载动画),不改变路由的底层执行逻辑,只是 “加一层过滤”。

  • 示例:Vue Router 的 beforeEach 守卫,拦截后要么 next() 放行,要么 next('/login') 重定向,路由的最终执行还是浏览器原生 History API。
2. 微前端 History 路由拦截

多应用(主 + 子)的 “路由沙箱劫持”:不仅拦截,还改写路由的底层执行逻辑(重写 history.pushState、劫持 popstate 事件),目的是实现 “主 - 子应用路由隔离 + 全局历史记录统一”,让多个子应用的路由看起来像 “单应用”。

  • 示例:Wujie 拦截子应用的 pushState('/proOrder'),自动拼接前缀变成 /vue3-app/proOrder,子应用感知不到,但全局 URL 已被改写。

二、核心差异对比(6 个维度)

对比维度传统单应用路由拦截(History 模式)微前端 History 模式路由拦截
核心目标单应用内的路由管控(鉴权、跳转控制、埋点)多应用路由隔离 + 全局历史记录统一 + 子应用无感知适配
拦截范围仅拦截当前应用自身的路由操作拦截「主应用 + 所有子应用」的全局路由操作
实现方式基于框架路由守卫(如 Vue Router beforeEach),仅 “监听 / 过滤”,不修改原生 API重写浏览器原生 history API(pushState/replaceState)+ 劫持 popstate 事件,改写底层逻辑
路由处理逻辑路由路径是 “应用内相对路径”(如 /proOrder),直接使用路由路径分 “全局路径”(/vue3-app/proOrder)和 “子应用内部路径”(/proOrder),需拼接 / 剥离前缀
历史记录管理仅维护自身应用的历史记录栈维护「全局统一的历史记录栈」,关联主 / 子应用的路由变化
事件处理监听自身的 popstate 事件,无冲突劫持所有子应用的 popstate 监听,包装后执行(避免事件冒泡 / 冲突)
框架依赖依赖单应用路由框架(Vue Router/React Router)依赖微前端框架(Wujie/Qiankun)的 “路由沙箱” 能力
侵入性对应用无侵入(仅加守卫)对子应用有轻量侵入(需适配路由监听,如禁用 history.listen

三、实战案例对比(更直观)

案例 1:传统 Vue 单应用路由拦截(你的 Vue3 子应用原生逻辑)

// 传统单应用(Vue3)的路由拦截:仅管控,不改写底层
router.beforeEach((to, from, next) => {
  // 目标:鉴权、改标题
  document.title = to.meta.title;
  if (to.meta.requiresAuth && !localStorage.getItem('token')) {
    next('/login'); // 拦截后重定向,路由底层逻辑不变
  } else {
    next(); // 放行,原生 pushState 执行
  }
});

// 点击跳转按钮时,执行原生 pushState,URL 直接变成 /proOrder
document.querySelector('#toProOrder').onclick = () => {
  history.pushState({}, '', '/proOrder'); // 原生 API,无改写
};

关键:拦截只做 “过滤 / 重定向”,history.pushState 还是浏览器原生方法,URL 就是子应用自己的路径,无拼接。

案例 2:微前端 Wujie 路由拦截(你的 Vue2 主应用 + Vue3 子应用)

// 1. 主应用:Wujie 重写子应用的 pushState(核心改写)
const rawPushState = window.history.pushState;
window.history.pushState = function(state, title, url) {
  // 改写逻辑:拼接子应用前缀 /vue3-app
  const fullUrl = '/vue3-app' + url; 
  return rawPushState.call(window.history, state, title, fullUrl);
};

// 2. 子应用点击跳转按钮时,看似调用原生 API,实则执行改写后的逻辑
document.querySelector('#toProOrder').onclick = () => {
  history.pushState({}, '', '/proOrder'); // 子应用感知不到改写
  // 实际全局 URL 变成:/vue3-app/proOrder(而非子应用以为的 /proOrder)
};

// 3. 主应用路由守卫:拦截全局 URL,识别子应用
router.beforeEach((to, from, next) => {
  if (to.path.startsWith('/vue3-app')) {
    loadVue3SubApp(); // 加载子应用
    const subPath = to.path.replace('/vue3-app', ''); // 剥离前缀得到 /proOrder
    setSubAppRoute(subPath); // 告诉子应用要渲染的路由
    next();
  }
});

关键:子应用调用的 pushState 是被改写后的方法,URL 被拼接前缀;主应用再通过前缀识别子应用,实现 “隔离 + 统一”。


四、关键差异的底层原因

  1. 场景复杂度不同
    • 传统单应用:只有一套路由规则,无需考虑 “多应用冲突”,拦截只需 “管控”;
    • 微前端:多应用共享同一个浏览器 history 对象,必须通过 “劫持 + 改写” 实现隔离,否则子应用的路由会覆盖主应用。
  2. 路由归属不同
    • 传统单应用:路由是 “应用私有” 的,URL 直接对应自身组件;
    • 微前端:路由是 “全局共享” 的,URL 需包含 “子应用标识 + 子应用路由”,因此必须拼接 / 剥离前缀。
  3. 历史记录诉求不同
    • 传统单应用:只需维护自身的历史记录,回退 / 前进只影响自身;
    • 微前端:需让用户感知不到 “多应用”,因此要统一管理全局历史记录,回退时需同时同步主 / 子应用的路由状态。

总结(核心关键点)

  1. 本质区别:传统拦截是 “单应用内的路由管控(过滤 / 重定向)”,不改写原生 API;微前端拦截是 “多应用的路由沙箱劫持”,改写原生 History API 实现隔离;
  2. 核心差异:微前端需要处理 “全局路径 + 子应用内部路径” 的转换(前缀拼接 / 剥离),而传统拦截只有 “应用内路径”;
  3. 最终效果:传统拦截不改变 URL 的底层格式,微前端拦截让子应用的路由 “看似独立,实则被主应用统一管理”;
  4. 结合你的场景:你在 Wujie 中配置的 prefix="/vue3-app",就是微前端拦截和传统拦截的核心区别体现 —— 传统路由不需要这个前缀,微前端必须靠它实现隔离。
### qiankun 微前端框架中使用 History 模式管理子系统路由的方案 在 qiankun 微前端框架中,使用 `history` 模式管理子系统的路由是一种常见且推荐的方式。以下是对该场景的具体分析实现方法: #### 1. 主应用的路由配置 主应用作为整个微前端体系的核心,需负责统一管理分发请求至各个子应用。如果主应用采用 `history` 模式,则可通过如下方式进行配置[^1]: ```javascript // router/index.js (主应用路由配置) import { createWebHistory, createRouter } from 'vue-router'; const routes = [ { path: '/', redirect: '/home', }, { path: '/home', component: () => import('@/views/Home.vue'), }, ]; const router = createRouter({ history: createWebHistory(), routes, }); export default router; ``` 在此基础上,在主应用启动时注册子应用并定义其路径匹配规则[^3]: ```javascript // main.js 或者专门的微前端入口文件 import { registerMicroApps, start } from 'qiankun'; import Vue from 'vue'; import App from './App.vue'; import router from './router'; Vue.config.productionTip = false; new Vue({ router, render: h => h(App), }).$mount('#app'); registerMicroApps([ { name: 'app1', entry: '//localhost:7101', container: '#subapp-container', activeRule: '/app1', // 子应用激活路径 }, ]); start(); ``` #### 2. 子应用的路由配置 对于子应用而言,当使用 `history` 模式时,需要特别注意设置正确的 `base` 路径,以确保子应用的路由能够正确嵌套在主应用之下[^3]。例如,子应用可以按照以下方式配置路由: ```javascript // app1/router/index.js (子应用路由配置) import { createWebHistory, createRouter } from 'vue-router'; const routes = [ { path: '/child-page1', component: () => import('@/views/ChildPage1.vue'), }, { path: '/child-page2', component: () => import('@/views/ChildPage2.vue'), }, ]; const base = window.__POWERED_BY_QIANKUN__ ? '/app1' : '/'; const router = createRouter({ history: createWebHistory(base), // 动态设置 base 路径 routes, }); export default router; ``` 这里的关键在于动态判断当前运行环境是否处于 qiankun 容器之中 (`window.__POWERED_BY_QIANKUN__`),如果是,则将 `base` 设置为主应用为其分配的路径前缀(如 `/app1`),否则默认为空字符串。 #### 3. 处理跨子应用跳转问题 在 `history` 模式下,跨子应用跳转可能引发页面刷新的问题。为了避免这种情况,可以在主应用中拦截所有的路由变化事件,并手动控制子应用的加载逻辑[^3]: ```javascript // 主应用中监听路由变化 window.addEventListener('popstate', () => { const currentPath = location.pathname; if (currentPath.startsWith('/app1')) { loadApp('//localhost:7101'); } else if (currentPath.startsWith('/app2')) { loadApp('//localhost:7102'); } }); ``` 其中,`loadApp` 是自定义函数用于加载指定的子应用。 #### 4. 嵌套路由的支持 为了更好地支持复杂的业务场景,qiankun 提供了对嵌套路由的良好支持。通过合理设计主应用与子应用之间的路径结构,可以使 URL 更加直观易懂。例如,假设有一个子应用名为 `app1`,它内部有两个页面分别为 `child-page1` `child-page2`,那么最终访问地址可能是这样的形式:`http://example.com/app1/child-page1`。 这种嵌套结构不仅有助于提升用户体验,还方便后续功能扩展及维护工作开展。 --- ### 总结 综上所述,在 qiankun 微前端框架中使用 `history` 模式管理子系统路由是一项重要技能点。通过对主应用与各子应用间的协作关系深入理解及相关技术手段灵活运用,可以构建出高效稳定又具有良好可读性的整体架构体系。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涔溪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值