微信浏览器bfcache 问题

bfcache 全称是Back/forward cache,指浏览器在前进/后退的过程中,现代浏览器在通常情况下会缓存住页面在内存中,用来提高页面加载速度和用户体验。

但既然是缓存,那么一段会存在缓存是否有效的问题。bfcache 也一样,在一些特地场景下,如果强制缓存住页面,可能会导致意料之外的问题,所以bfcache 的生效也有一些限制。如果想详细了解bfcache,可以浏览https://web.dev/bfcache/

当在一个文章列表页中,点击了一个外链跳转的其他的页面后,再点击返回,我们可能期待的是:返回有页面不用重新加载,并且滚动条在原来的位置处。

如果是支持bfcache 的场景下,因为页面是被缓存住的,js 并没有执行,没有重新渲染,以上效果是可以达成的。

然而,由于在微信当中,微信的IOS 版本是wkwebview,支持bfcache,但在微信的安卓浏览器中,却是不支持bfcache的,为了达到相同的用户体验,无奈之下只能用js 来实现。

实现的思路也比较简单:

  1. 在用户跳转外链之前,把js store 中的数据和滚动条位置持久化保存在本地。
  2. 判断用户是通过返回键回到页面,且本地存在持久化数据,则还原本地数据,不发起网络请求。
  3. 为了防止本地持久化数据异常对用户造成影响,使用sessionStorage,用户关闭页面后会被自动清空。

以上方案目前运行良好,安卓使用js 模拟bfcache,IOS 使用原生的bfcache。

但后来遇到一个问题,网上查了很久也没有资料,花了很多时间,于是记录一下。

经过几天的功能迭代,IOS 的bfcache 在部分页面突然失效了。排查了可能让bfcache 失效的一堆原因,并没有找到问题。最后注释掉微信分享相关的代码,发现bfcache 恢复,于是去查看了相关源码,找到了一部分可疑代码。

在实现微信分享的过程中,我使用了一个开源的第三方库 wechat-jssdk,查看这个库的源码,发现他在每次初始化库的时候,会先执行一个`loadScript` 的函数去动态加载js。

怀疑是这段动态加载微信js sdk 的代码导致的bfcache 失效,虽然chrome 相关文档没有找到动态加载js 会导致bfcache 失效的相关介绍,但缓存中被执行了新的js ,很可能会失效。

loadScript() {
    return new Promise((resolve, reject) => {
      const ele = document.createElement('script');
      ele.type = 'text/javascript';
      ele.async = true;
      ele.onload = () => {
        console.log('Wechat script loaded successfully!');
        //init the wechat config
        this.signSignature()
          .then(instance => {
            resolve(instance);
          })
          .catch(err => {
            reject(err);
          });
      };
      ele.onerror = err => {
        console.error('Failed to load wechat script!');
        console.error(err);
        this.debug && alert('Cannot load wechat script!');
        reject(err);
      };
      const linkEle = document.getElementsByTagName('script')[0];
      linkEle.parentNode.insertBefore(ele, linkEle);
      ele.src = this.sdkUrl;
    });
  }

于是注释掉这段代码,直接在head 中引入js sdk ,问题终于得到了解决。


过了几个月又踩到bfcache 的坑了,记录一下。

背景是莫名其妙的,微信iOS 中bfcache 又失效了,花了大概4小时定位问题。

  1. 首先使用chrome 调试工具,Application>>back/forward cache tab 下的测试工具来检测有哪些导致缓存失效的问题。刚开始我检测出了一个使用了unload 事件的问题,但代码排查,查看dom 事件等,并没有使用到。后来突然想到,可能是浏览器插件导致的,换隐身模式查看,果然没了。
  2. chrome 检测通过了,但ios 微信中还是不行。于是在Safari浏览器调试。但Safari 浏览器显示正常。也就是说只有在微信ios 里异常。
  3. 本来准备放弃了,但查看竞品可以,那一定是代码有问题。
  4. 没有思路,二分法注释掉一些可疑代码排查。结果离了大普,竟然是注册微信分享的函数导致的,并且,只是其中的一些属性,我注册了<wx-open-launch-app/> 标签来唤醒APP , 结果导致了bfcache失效,去掉之后就ok 了。 还好ios 中我是用universal link 唤醒app , 并不依赖。
const config = {
      appId: "",
      nonceStr: "",
      signature: "",
      timestamp: "",
      jsApiList: ["updateAppMessageShareData", "updateTimelineShareData", "onMenuShareWeibo", "onMenuShareQZone"], //设置所有想要使用的微信jsapi列表, 默认值为 ['onMenuShareTimeline', 'onMenuShareAppMessage'],分享到朋友圈及聊天记录
      openTagList: isIOS() ? [] : ["wx-open-launch-app"], //居然是这个属性导致的bfcache 失效
      ...signature,
    };
    window.wx.config(config);

Leave a Comment

邮箱地址不会被公开。 必填项已用*标注