微信浏览器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 ,问题终于得到了解决。

Leave a Comment

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