【译文】Service Worker缓存和HTTP缓存

原文:Service worker caching and HTTP caching
作者:Jonathan Chen

本周使用了一个webpack 插件 offline-plugin ,他使用了 Service Worker 对网站静态进行缓存,你只要在webpack.conf.js中引入配置,在main.js中加入runtime配置就行,它会对你所有的webpack构建的资源进行缓存, 对servie worker 的js使用时间戳进行请求,确保每次构建后sw文件保证最新,从而保证缓存你的静态资源是最新的 (请查看下篇文章解释Service Worker文件需要缓存吗?)。上线后测试了下,效果还可以,在Network下查看缓存后,静态访问一般都是2ms或者3ms左右,访问都是从Service Worker,而之前出现的 Memory Cache(HTTP缓存不是存在Memory Cache中的,参考浏览器缓存之http缓存和service worker)或者Disk Cache都不见了(在开启浏览器缓存下),我就有点疑惑了 ,Service Worker缓存和HTTP缓存之间的优先级到底是那个最高?于是找到了这篇文章。。。

当Servie Worker和PWA成为现在现代web应用的标准时,资源缓存变得以往更加复杂。这篇文章包括了浏览器缓存,包括:

  1. Service Worker缓存和HTTP缓存用例和他们之间的区别
  2. Service Worker缓存到期策略和常规HTTP缓存之间的优点和缺点

缓存流程描述

在上层来看,浏览器在请求资源的时候遵循以下缓存顺序:

  1. Service Worker:Service Worker检查资源是否已经缓存,并根据编程的缓存策略决定是否返回资源本身。请注意,这不会主动触发。你需要在你的Service Worker文件中创建一个fetch事件处理程序,并拦截网络请求,以便从Service Worker缓存中获取而不是通过网络请求。

  2. HTTP缓存(也就是浏览器缓存):如果发现资源在HTTP缓存中,并且没有过期,浏览器将使用HTTP缓存中的资源(Memory Cache或者Disk Cache)。

  3. 服务器端:如果在Service Worker缓存和HTTP缓存未找到,浏览器会通过网络请求资源。如果资源也没有在CDN缓存中,请求必须一直返回到原始服务器。

请注意,某些浏览器(比如说Chrome)在Service Worker缓存之前会只有一个内存缓存层。内存缓存的详细信息取决于每个浏览器的具体实现。不幸的是,这部分还没有明确的规定。

缓存层

Service Worker缓存

Servcie Worker拦截网络类型的HTTP请求,并使用缓存策略来确定应该将哪些资源返回给浏览器。Servcie Worker缓存和HTTP缓存具有相同的目的,但是Servcie Worker缓存提供了更多的缓存功能,例如精确控制要缓存的内容和完成缓存的方式。

控制Servcie Worker缓存

Servcie Worker使用事件侦听器(通常是fetch事件)。这个代码片段展示了缓存优先缓存策略的逻辑:

推荐使用Workbox 以避免重复造轮子。例如,你可以注册资源url路径使用一行正则匹配

import {registerRoute} from 'workbox-routing';

registerRoute(new RegExp('styles/.*\.css'), callbackHandler);

Service worker缓存策略和用例

下表描述了常见的Service worker 缓存策略以及每一种策略合何时有用。

策略 刷新机制 用例
Network only 内容必须始终是最新的 1. 付款和结账 2. 余额表
Network falling back to cache 最好提供最新的内容。如果网络请求失败或者不可用,使用稍微旧的的内容也是可以接受的 1.及时的数据 2.价格和汇率(需要免责声明)3.订单状态
Stale-while-revalidate 可以立即提供缓存的内容,但是在将来会使用更新过的缓存 1.新闻提要 2. 产品列表页 3.消息
Cache first, fall back to network 内容不是很重要,为了性能提升可以使用缓存,但是Service Worker应该偶尔更新下缓存 1.应用程序外壳 2.共用资源
Cache only 内容很少变化 纯静态内容

service worker的其他好处

servcie worker处理对缓存逻辑的精细控制外,还提供:

  • 在域中减少的内存使用和存储使用:浏览器按照域来分配HTTP缓存资源。也就是说,如果你有多个子域,它们共享相同的HTTP缓存。无法保证域/源中的内容会长时间保留在HTTP缓存中。比如,用户通过浏览器的设置ui手动清除缓存,或者触发强制刷新来清除缓存。使用servcie worker缓存,您缓存的内容保持缓存的可能性更高
    的可能性(当然你得选择正确的缓存策略)。查看永久存储查看更多。

  • 不稳定的网络或者离线体验提供更高的灵活性:使用HTTP缓存你只有2种选择:资源有缓存或者没有。使用servcie worker缓存,你可以更简单些(使用stale-while-revalidate策略),提供完整的离线体验(使用Cache only策略),或者在两者之间,像ui部分的页面从service worker中去,而其他部分除外(使用Set catch handler策略)在适当情况下。

HTTP缓存

当浏览器第一次加载网页和相关资源时,会将这些资源存储在其HTTP缓存中。HTTP缓存通常由浏览器默认开启,除非用户明确禁用了HTTP缓存。

使用HTTP缓存就意味着依靠服务器端决定是否缓存以及缓存多长时间(其实就是HTTP协议约定)。

HTTP响应头决定HTTP缓存失效

当服务器响应浏览器对资源的请求时,HTTP响应头告诉浏览器应该缓存资源多长时间。更多请查看Response headers: configure your web server

HTTP缓存策略和用例

HTTP缓存比service worker缓存简单很多,因为HTTP缓存只处理基于时间(TTL)的资源过期逻辑。详情查看Which response header values should you use? 来学习更多的缓存策略。

设计你的缓存过期逻辑

这部分说明了在service worker缓存和HTTP缓存协同使用之间的到期逻辑的优缺点,以及单独使用的到期逻辑的优缺点。

下边的故障演示了在不同情况下service worker缓存和HTTP缓存如何工作:

https://glitch.com/edit/#!/compare-sw-and-http-caching?path=README.md%3A1%3A0

缓存层的一致过期逻辑

为了展示其优缺点,我们查看3中场景:长期,中期和短期

Scenarios Long-term caching Medium-term caching Short-term caching
Service worker 缓存策略 Cache, falling back to network Stale-while-revalidate Network falling back to cache
Service worker 缓存 TTL 30 days 1 day 10 mins
HTTP 缓存 max-age 30 days 1 day 10 mins

场景:长期缓存(Cache, falling back to network)

  • 当缓存资源有效(小于等于30天):service worker缓存没有网络而是直接返回缓存的资源

  • 当缓存资源过期(大于30天):service worker通过网络获取资源。浏览器的HTTP缓存中没有该资源的副本,因此去服务端请求数据

结论:在这个场景中,HTTP缓存提供的价值较小,因为在service worker缓存失效时,浏览器始终将请求传递到服务器端。

场景:中期缓存(Stale-while-revalidate)

  • 当缓存资源有效(小于等于1天):service worker立即返回缓存的资源,然后转到网络以获取资源。浏览器在HTTP缓存具有资源的副本,因此它将该副本返回servcie worker。

  • 当缓存资源过期(大于一天):service worker立即返回缓存的资源,然后转到网络以获取资源。浏览器的HTTP缓存中没有该资源的副本,因此去服务端请求数据

结论:service worker 需要额外的缓存清除来覆盖HTTP缓存,以便充分利用重新验证步骤。

场景:短期缓存(Network falling back to cache)

  • 当缓存资源有效(小于等于10分钟):service worker通过网络去获取资源。浏览器有该资源的副本,因此返回该资源给service worker而没有走服务器端。

  • 当缓存资源失效(大于10分钟):service worker通过网络去获取资源。浏览器的HTTP缓存中没有该资源的副本,因此去服务端请求数据。

结论:跟中期缓存相似,service worker 需要额外的缓存清除来覆盖HTTP缓存,以便充分利用重新验证步骤。

service worker在所有场景

在所有场景中,service worker缓存可以返回缓存的资源当网络不可用时。另一方面,HTTP缓存在网络挂掉或者不可用时是不可靠的。

在servcie worker缓存和HTTP缓存层的不同的缓存过期策略:

为了展示优缺点,我们再次查看长期,中期和短期场景。

Scenarios Long-term caching Medium-term caching Short-term caching
Service worker caching strategy Cache, falling back to network Stale-while-revalidate Network falling back to cache
Service worker cache TTL 90 days 30 days 1 day
HTTP cache max-age 30 days 1 day 10 mins

场景:长期缓存(Cache, falling back to network)

  • 当缓存资源在servcie worker有效(小于等于90天):service worker缓存直接返回缓存的资源

  • 当缓存资源在servcie worker失效(大于90天):service worker通过网络获取资源。浏览器的HTTP缓存中没有该资源的副本,因此去服务端请求数据。

优缺点:

  • 优点:当service worker立即返回缓存的资源时,用户会体验到及时响应

  • 优点:servcie worker可以更加精细的控制何时使用缓存和何时请求新版本的资源。

  • 缺点:需要一个定义明确的service worker缓存策略

场景:中期缓存(Stale-while-revalidate)

  • 当缓存资源在servcie worker有效(小于等于30天):service worker缓存直接返回缓存的资源

  • 当缓存资源在servcie worker失效(大于30天):service worker通过网络获取资源。浏览器的HTTP缓存中没有该资源的副本,因此去服务端请求数据。

优缺点:

  • 优点:当service worker立即返回缓存的资源时,用户会体验到及时响应

  • 优点:在“后台”发生的重新验证,servcie worker可以对给定的URL使用网络的新响应

  • 缺点:需要一个定义明确的service worker缓存策略

场景:短期缓存(Network falling back to cache)、

  • 当缓存资源在servcie worker有效(小于等于1天):service worker通过网络去获取资源。浏览器有该资源的副本,因此返回该资源给service worker而没有走服务器端。如果浏览器没有网络,servcie worker后返回缓存资源

  • 当缓存资源在servcie worker失效(大于1天):service worker通过网络去请求资源。浏览器获取资源通过网络当HTTP缓存失效时。

优缺点:

  • 优点:当网络不可用,service worker立即返回缓存的资源时

  • 缺点:servie worker需要其他缓存清除来覆盖HTTP缓存,并发出网络优先的请求。

总结

考虑到缓存方案组合的复杂性,设计一个涵盖所有情况的规则是不可能的。但是,基于前几节的发现,在设计缓存策略的时候,有一些建议可供参考:

  • service worker缓存逻辑不要和HTTP缓存到期逻辑保持一致,在service worker中使用更长的到期逻辑,以便授予servcie worker更多的控制权。

  • HTTP缓存依然扮演一个重要的角色,但是在网络不可用的时候是不可靠的

  • 重新访问每种资源的缓存策略,以确保你的servcie worker缓存策略提供其价值,而不会域HTTP缓存发生冲突。

参考资料:

原文地址:https://www.cnblogs.com/hanshuai/p/14646302.html