qiankun微应用历史记录管理:实现浏览器前进后退功能

qiankun微应用历史记录管理:实现浏览器前进后退功能

【免费下载链接】qiankun 📦 🚀 Blazing fast, simple and complete solution for micro frontends. 【免费下载链接】qiankun 项目地址: https://gitcode.com/gh_mirrors/qiankun5/qiankun

在微前端架构中,用户常常遇到浏览器前进后退按钮失效的问题,导致用户体验下降。qiankun作为一款成熟的微前端解决方案,通过精心设计的历史记录管理机制,完美解决了这一痛点。本文将详细介绍qiankun如何实现微应用的历史记录管理,帮助开发者轻松掌握浏览器前进后退功能的实现方法。

qiankun历史记录管理核心原理

qiankun的历史记录管理功能主要通过劫持浏览器的历史记录API和监听popstate事件来实现。其核心思想是在主应用和微应用之间建立一个统一的历史记录管理机制,确保微应用的路由变化能够被正确地反映到浏览器的历史记录中,同时也能够正确响应浏览器的前进后退操作。

历史记录劫持实现

qiankun通过src/hijackers/historyListener.ts文件实现了对浏览器历史记录相关API的劫持。该文件中的hijack函数会重写window.g_history.listen方法,从而实现对历史记录变化的监听和管理。

// src/hijackers/historyListener.ts
export default function hijack() {
  let rawHistoryListen = (_: any) => noop;
  const historyListeners: Array<typeof noop> = [];
  const historyUnListens: Array<typeof noop> = [];

  if ((window as any).g_history && isFunction((window as any).g_history.listen)) {
    rawHistoryListen = (window as any).g_history.listen.bind((window as any).g_history);

    (window as any).g_history.listen = (listener: typeof noop) => {
      historyListeners.push(listener);

      const unListen = rawHistoryListen(listener);
      historyUnListens.push(unListen);

      return () => {
        unListen();
        historyUnListens.splice(historyUnListens.indexOf(unListen), 1);
        historyListeners.splice(historyListeners.indexOf(listener), 1);
      };
    };
  }

  // ...
}

这段代码的主要作用是:

  1. 保存原始的history.listen方法
  2. 重写history.listen方法,将所有的监听器收集到historyListeners数组中
  3. 返回一个用于恢复原始history.listen方法的函数

历史记录恢复机制

当微应用卸载时,qiankun会自动清理该微应用注册的历史记录监听器,并在需要时重新绑定这些监听器。这一功能通过hijack函数返回的free函数实现。

// src/hijackers/historyListener.ts
return function free() {
  let rebuild = noop;

  if (historyListeners.length) {
    rebuild = () => {
      historyListeners.forEach(listener => (window as any).g_history.listen(listener));
    };
  }

  // 卸载余下的 listener
  historyUnListens.forEach(unListen => unListen());

  // restore
  if ((window as any).g_history && isFunction((window as any).g_history.listen)) {
    (window as any).g_history.listen = rawHistoryListen;
  }

  return rebuild;
};

主应用中的历史记录配置

在qiankun的主应用中,我们需要通过start方法的配置项来启用和配置历史记录管理功能。主应用的入口文件examples/main/index.js展示了如何进行配置:

// examples/main/index.js
start({
  prefetch: true,
  jsSandbox: true,
  singular: true,
  fetch: window.fetch,
});

其中,singular: true配置项表示启用单例模式,即同一时刻只允许一个微应用处于激活状态。这一配置对于历史记录管理至关重要,因为它确保了在同一时刻只有一个微应用在操作历史记录。

微应用注册与路由匹配

主应用通过registerMicroApps方法注册微应用时,需要指定每个微应用的activeRule,即路由匹配规则。这一规则决定了何时激活哪个微应用,是实现历史记录管理的基础。

// examples/main/index.js
function genActiveRule(routerPrefix) {
  return location => location.pathname.startsWith(routerPrefix);
}

registerMicroApps(
  [
    {
      name: 'react16',
      entry: '//localhost:7100',
      render,
      activeRule: genActiveRule('/react16'),
    },
    {
      name: 'vue',
      entry: '//localhost:7101',
      render,
      activeRule: genActiveRule('/vue'),
    },
    // 其他微应用...
  ],
  // ...
);

微应用中的历史记录处理

不同框架的微应用在集成qiankun时,需要进行一些特定的配置来确保历史记录管理功能的正常工作。下面以React和Vue微应用为例,介绍如何进行配置。

React微应用配置

在React微应用中,我们需要在入口文件中设置publicPath,并使用history库来管理路由。以examples/react16/src/index.js为例:

// examples/react16/src/index.js
import './public-path';
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

function render(props) {
  const { container } = props;
  ReactDOM.render(
    <BrowserRouter basename="/react16">
      <App />
    </BrowserRouter>,
    container ? container.querySelector('#root') : document.querySelector('#root')
  );
}

// ...

Vue微应用配置

在Vue微应用中,我们需要在路由配置中设置base选项,并在入口文件中设置publicPath。以examples/vue/src/router/index.js为例:

// examples/vue/src/router/index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '../views/Home.vue';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
];

const router = new VueRouter({
  mode: 'history',
  base: window.__POWERED_BY_QIANKUN__ ? '/vue' : '/',
  routes
});

export default router;

实现前进后退功能的完整流程

下面通过一个流程图来展示qiankun实现微应用历史记录管理的完整流程:

mermaid

常见问题与解决方案

问题1:微应用切换后浏览器前进后退按钮失效

这一问题通常是由于微应用没有正确配置路由的basebasename选项导致的。解决方案是确保每个微应用的路由base与主应用注册时的activeRule保持一致。

问题2:多个微应用之间切换时历史记录混乱

这一问题通常是由于没有启用单例模式导致的。解决方案是在主应用的start方法中设置singular: true,确保同一时刻只有一个微应用处于激活状态。

问题3:微应用卸载后历史记录监听器没有被正确清理

这一问题可以通过qiankun的historyListener劫持机制来解决。qiankun会在微应用卸载时自动清理其注册的历史记录监听器,确保不会出现内存泄漏和历史记录混乱的问题。相关实现可以参考src/hijackers/historyListener.ts文件。

总结

qiankun通过劫持浏览器的历史记录API和监听popstate事件,实现了微应用的历史记录管理功能。这一功能的核心在于src/hijackers/historyListener.ts文件中的劫持和恢复机制,以及主应用中singular: true的配置。

通过本文的介绍,我们了解了qiankun实现微应用历史记录管理的核心原理和具体实现方法。在实际开发中,我们需要注意以下几点:

  1. 确保主应用中启用了单例模式(singular: true)
  2. 为每个微应用配置正确的路由basebasename
  3. 理解qiankun的历史记录劫持机制,避免重复监听或错误清理

掌握了这些知识,我们就能够在qiankun微前端架构中轻松实现浏览器前进后退功能,为用户提供更加流畅的体验。

【免费下载链接】qiankun 📦 🚀 Blazing fast, simple and complete solution for micro frontends. 【免费下载链接】qiankun 项目地址: https://gitcode.com/gh_mirrors/qiankun5/qiankun

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

抵扣说明:

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

余额充值