使用传统前端技术增强客户端缓存能力

栏目: 前端 · 发布时间: 5年前

内容简介:前几天重构之后,Lighthouse 中有一个评分让我念念不忘:说到

前几天重构之后,Lighthouse 中有一个评分让我念念不忘: Progressive Web App

PWA 不算一个新话题了,所以概念性的东西和 API 我就不多做介绍,下面简单介绍一个无干预更新的缓存方案,整体代码量在一百行以内,如果你也想在不“大动干戈”的情况下对站点或者 Web App 进行性能提升的话,可以了解一下。

浏览器客户端代码

说到 PWA ,我们能直接想到的,无非是 增强缓存推送能力 。而这两个能力,都是 ServiceWorker API 实现的。(添加桌面图标这个需求,我不需要,就不介绍了,感兴趣可以自行搜索)

我在之前的重构文章中有简单聊过访客数据,其中有一部分访客使用的客户端并不支持 Service Worker ,所以在使用它的时候,需要使用 能力探测 的方式引入,比如:

try {
  ('serviceWorker' in navigator) && navigator.serviceWorker.register('/sw.js');
} catch (error) {
  console.error(error);
}

当然,构建压缩之后,你得到的结果应该是 drop console 的最简代码。不过,如果你不确定你的运行环境是否有问题,可以使用下面带有调试日志的版本。

try {
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.min.js').then(function(registration) {
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }).catch(function(err) {
      console.error('ServiceWorker registration failed: ', err);
    });
  }
} catch (error) {
  console.error(error);
}

ServiceWorker 客户端代码

上面介绍浏览器客户端代码的时候,有引入一个外部脚本依赖 sw.js

在分享代码之前,有做过 PWA 相关项目或者了解的同学,可能或多或少会在 增强缓存 这个地方被坑到,比如:缓存无法更新、缓存内容过多无法写入。

缓存无法更新有一个简单有效的解决方案:定时切换缓存使用的 Store 。如果再引入 当前时间 这个因素,可以保障缓存使用的 Store 不存在资源争抢的问题。

结合站点内容特点,配合定期清理缓存的脚本,可以将缓存数量控制在一定的范围之内。

这里提供一个小思路,对服务端资源进行二次缓存的时候,可以设定一个最大缓存时间的策略,而这里有两个方案:

TTL
TTL

我个人选择第二个方案,牺牲一定的缓存复用,但是有效降低资源之间的版本管理的复杂度。

而需要缓存的资源一般分为两类:

  • 短时间缓存:页面或者页面片段
  • 相对长时间缓存:图片等媒体资源,或者有一定跨页面通用能力的脚本和样式资源

这里以10分钟(调试模式单位替换为秒)为一个时间段,为短时间缓存的资源进行缓存。设定星期数为其他资源进行缓存周期。

这里我们不必过分处理 installactive 事件,只需要统一在 fetch 事件中进行缓存更新和清理即可,比如下面这样:

function weekId() {
  var now = (new Date());
  var dt = new Date(now.getFullYear(), 0, 1);
  return Math.ceil((((now - dt) / 86400000) + dt.getDay() + 1) / 7);
}
 
var isDevMode = false;
var CACHE_LONG_TTL = 'WEEK_' + weekId();
var CACHE_TINY_TTL = 'TINY_';
 
function cleanCache(whiteList) {
  return caches.keys().then(function(buckets) {
    return Promise.all(buckets.filter(function(bucket) {
      return whiteList.indexOf(bucket) === -1;
    }).map(function(bucket) {
      return caches.delete(bucket);
    }));
  });
}
 
self.addEventListener('activate', function(event) {
  event.waitUntil(cleanCache([CACHE_LONG_TTL]));
});
 
self.addEventListener('fetch', function(event) {
 
  var url = new URL(event.request.url);
  if (url.protocol.toLowerCase() !== 'https:') return;
 
  var now = new Date;
  var CACHE_INTERVAL = Math.floor((isDevMode ? now.getSeconds() : now.getMinutes()) / 10);
  var CACHE_KEY = CACHE_TINY_TTL + CACHE_INTERVAL;
 
  if (url.pathname.endsWith('/') ||
      url.pathname.endsWith('.html') ||
      url.pathname.endsWith('.md') ||
      url.pathname.endsWith('/feed/') ||
      url.pathname.endsWith('/feed') ||
      url.pathname.endsWith('sw.js')) {
 
    cleanCache([CACHE_LONG_TTL, CACHE_KEY]);
 
    event.respondWith(caches.open(CACHE_KEY).then(function(cache) {
      return cache.match(url).then(function(response) {
        if (response) return response;
        return fetch(event.request).then(function(response) {
          cache.put(event.request, response.clone());
          return response;
        });
      });
    }));
 
  } else {
    event.respondWith(caches.open(CACHE_LONG_TTL).then(function(cache) {
      return cache.match(event.request).then(function(response) {
        if (response) return response;
        return fetch(event.request).then(function(response) {
          cache.put(event.request, response.clone());
          return response;
        });
      });
    }));
  }
 
});

如果你的访客有不少是 Chrome v50FireFox v46 以下的客户端,那么你可能还需要引入下面的 Polyfill : https://github.com/dominiccooney/cache-polyfill/blob/master/index.js

当然,在引入的时候,建议还是进行压缩,进一步提高页面性能(哪怕它是独立于客户端脚本另外的异步进程)。

当一切都完成之后,如果顺利的话,你的网站的将支持有限时间(本文是10min)的离线访问,以及重复访问时更好的响应能力。

另外,你也不需要担心 sw.js 被缓存后,这个站点变成“完全离线”。因为 sw.js 按照规范可以保证它的最长存在生命周期是 1天,也就是说,未来你的策略更新最多延迟1天。

最后

使用传统前端技术增强客户端缓存能力

再次跑分,发现 Lighthouse 已经全面绿色评价了,不过前文中我提过,我不太需要把网站变为纯粹的 PWA 应用,没有去设定 mainfest ,所以,依旧有 4 点改进建议。

  1. 用户不能够“安装” Web App。
  2. 没有定义启动屏幕(仿客户端体验)。
  3. 没有定义顶栏的主题色。
  4. viewport 没有优化。

这些后面再说吧。

— EOF


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

網絡社會之崛起

網絡社會之崛起

曼威·柯司特 / 夏鑄九、王志弘 等 / 唐山 / 2000-11 / NT$550

本書解釋了今日重塑世界的兩股強大但相互衝突的潮流:全球化與認同。資訊科技的革命以及資本主義的再結構已經引動了網絡社會,並帶來了策略,除經濟行為的全球化、工作的彈性化與不穩定,以及真實的虛擬文化。但是,伴隨著資本主義的轉化與國家主義的消亡而來的,是集體認同的表達以火力十足的方式竄起。它們挑戰了全球化中的文化單一性以及對於生活、環境的控制。曼威.柯司特在本書中描繪了社會運動的根源、目標以及效果,包括了......一起来看看 《網絡社會之崛起》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具