qiankun问题排查记录

一、问题描述

1.项目相关配置: umi + qiankun + ahooks, 在项目开发过程中碰到这样一个场景:条件改变列表进行筛选并使用useUrlState改变url参数,结果发现操作一次页面被渲染2次

2.复现方式: umi + qiankun(2.4.0以下版本), 注册qiankun:{master:{}},然后更新history就会触发

二、问题排查

排查思路: 组件—页面, 业务逻辑— 相关api—依赖 顺序来排除

1.组件逻辑排查
2.页面逻辑排查
3.相关api及配置 排查
1.api排查

经过查看ahooks源码,发现useUrlState内部调用update来强制更新(更新会和history更新合并),为了排查下是否是由于update的更新引起的,项目内手动写入useUrlState函数,去掉update来测试猜想是否正确,经过测试发现,2次渲染与update并无关系,只要histroy改变就会触发

  ....
  const setState = (s: React.SetStateAction<state>) => {
    const newQuery = typeof s === 'function' ? (s as Function)(targetQuery) : s;

    // 1. 如果 setState 后,search 没变化,就需要 update 来触发一次更新。比如 demo1 直接点击 clear,就需要 update 来触发更新。
    // 2. update 和 history 的更新会合并,不会造成多次更新
    update((v) => !v);
    history[navigateMode]({
      hash: location.hash,
      search: stringify({ ...queryFromUrl, ...newQuery }, parseConfig) || '?',
    });
  };
  ....
2.qiankun相关配置排查

plugin-qiankun 插件配置相当简单, mater和slave两种, 经过测试发现 只要 qiankun 注册 mater然后更新history就会触发

经过初步测试结论为: qiankun注册master:{} 就会触发2次渲染的bug

3.qiankun 逻辑排查

排查qiankun逻辑需要先熟悉了解qiankun源码,qiankun源码篇幅较大,后一篇文章单独描述

排查一遍qiankun源码并未发现触发2次渲染可能会出现的问题,只能继续往下排查single-spa框架

4.single-spa 框架排查

经过翻看single-spa源码及各版本更新记录比对发现,5.8.1以前版本popstate事件会执行2次,5.8.2之后修复加了判断start之后再执行

5.8.1源码

function patchedUpdateState(updateState, methodName) {
  return function () {
    const urlBefore = window.location.href;
    const result = updateState.apply(this, arguments);
    const urlAfter = window.location.href;

    if (!urlRerouteOnly || urlBefore !== urlAfter) {
      window.dispatchEvent(
        createPopStateEvent(window.history.state, methodName)
      );
    }

    return result;
  };
}

5.8.2源码 isStarted()就是用来判断start是否执行

function patchedUpdateState(updateState, methodName) {
  return function () {
    const urlBefore = window.location.href;
    const result = updateState.apply(this, arguments);
    const urlAfter = window.location.href;

    if (!urlRerouteOnly || urlBefore !== urlAfter) {
      if (isStarted()) {
        // fire an artificial popstate event once single-spa is started,
        // so that single-spa applications know about routing that
        // occurs in a different application
        window.dispatchEvent(
          createPopStateEvent(window.history.state, methodName)
        );
      } else {
        // do not fire an artificial popstate event before single-spa is started,
        // since no single-spa applications need to know about routing events
        // outside of their own router.
        reroute([]);
      }
    }

    return result;
  };
}
三、影响范围及处理方式
1.影响范围

​ qiankun 2.3.1-2.4.0

由于qiankun2.3.1为了处理loadMicroApp手动加载页面不跳转的问题写死single-spa版本为2.3.1 一直到2.4.0版本,所以这些版本都存在这个问题

2.处理方式

此bug以通过lssues提交给qiankun官方,官方不会对老版本做升级,不符合版本规范,所以业务侧通过升级qiankun版本(跳过这些问题版本)来解决此bug

结束语: 写到这里,这次qiankun问题排查已告一段落,记录文档是方便后面如果有人遇到此类问题方便定位,如果写的不当之处还望多多指教

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值