Service Worker 缓存和 HTTP 缓存

跨 Service Worker 缓存和 HTTP 缓存层使用一致或不同的过期逻辑的优缺点。

虽然 Service Worker 和 PWA 正在成为现代 Web 应用的标准,但资源缓存比以往任何时候都更复杂。本文介绍了浏览器缓存的概况,包括:

  • Service Worker 缓存与 HTTP 缓存的用例及其差异。
  • 与常规 HTTP 缓存策略相比,不同 Service Worker 缓存过期策略的优缺点。

缓存流程概览

大体上讲,浏览器在请求资源时将遵循以下缓存顺序:

  1. Service Worker 缓存:Service Worker 会检查资源是否在其缓存中,并根据其编程缓存策略决定是否返回资源本身。请注意,此过程不会自动完成。您需要在 Service Worker 中创建提取事件处理脚本并拦截网络请求,以便从 Service Worker 的缓存(而不是网络)处理请求。
  2. HTTP 缓存(也称为浏览器缓存):如果资源可在 HTTP 缓存中找到且尚未过期,则浏览器会自动使用 HTTP 缓存中的资源。
  3. 服务器端:如果在 Service Worker 缓存或 HTTP 缓存中找不到任何资源,浏览器会连接到网络以请求资源。如果资源未缓存在 CDN 中,则请求必须始终返回到源服务器。

缓存流程

缓存层

Service Worker 缓存

Service Worker 会拦截网络类型的 HTTP 请求,并使用缓存策略来确定应该向浏览器返回哪些资源。Service Worker 缓存和 HTTP 缓存服务于相同的一般用途,但 Service Worker 缓存提供更多缓存功能,例如精确控制缓存内容以及缓存方式。

控制 Service Worker 缓存

Service Worker 使用事件监听器(通常是 fetch 事件)拦截 HTTP 请求。此代码段演示了 Cache-First 缓存策略的逻辑。

展示 Service Worker 如何拦截 HTTP 请求的图表

强烈建议使用 Workbox,以避免重复劳动。例如,您可以使用一行正则表达式代码注册资源网址路径

import {registerRoute} from 'workbox-routing';

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

Service Worker 缓存策略和用例

下表概述了常见的 Service Worker 缓存策略以及每种策略何时有用。

策略 新鲜度理由 用例
仅限网络 内容必须始终保持最新状态。
  • 付款和结账
  • 余额对账单
网络回退到缓存 最好提供新鲜内容。但是,如果网络出现故障或不稳定,可以传送稍旧的内容。
  • 及时提供数据
  • 价格和费率(需要提供免责声明)
  • 订单状态
Stale-while-revalidate 可以立即提供缓存的内容,但将来应使用更新后的缓存内容。
  • 新闻 Feed
  • 产品列表页面
  • 消息
缓存优先,回退到网络 这些内容是非关键内容,可以通过缓存提供以提升性能,但 Service Worker 应偶尔检查更新。
  • 应用 Shell
  • 通用资源
仅缓存 内容很少发生变化。
  • 静态内容

Service Worker 缓存的其他优势

除了对缓存逻辑进行精细控制之外,Service Worker 缓存还提供以下功能:

  • 更多源站内存和存储空间:浏览器按源站分配 HTTP 缓存资源。换句话说,如果您有多个子网域,则这些子网域均共享相同的 HTTP 缓存。我们无法保证源站/网域的内容会在 HTTP 缓存中长时间保留。例如,用户可能会通过从浏览器的设置界面中手动清理缓存,或触发网页硬重载来清除缓存。借助 Service Worker 缓存,缓存内容保持缓存状态的可能性要高得多。如需了解详情,请参阅永久性存储
  • 在网络不稳定或离线体验方面具有更高的灵活性:使用 HTTP 缓存时,您只能选择二进制文件:资源是否缓存。借助 Service Worker 缓存,您可以更轻松地缓解一些小“小问题”(使用“stale-while-revalidate”策略),提供完整的离线体验(使用“Cache only”策略),甚至可以提供两者之间的某些体验,例如自定义界面,其中页面部分来自 Service Worker 缓存,而某些部分在适当情况下排除(使用“设置捕获处理程序”策略)。

HTTP 缓存

浏览器首次加载网页和相关资源时,会将这些资源存储在其 HTTP 缓存中。除非最终用户明确停用 HTTP 缓存,否则浏览器通常会自动启用它。

使用 HTTP 缓存意味着依赖于服务器来确定何时缓存资源以及缓存多长时间。

使用 HTTP 响应标头控制 HTTP 缓存过期时间

当服务器响应浏览器对资源的请求时,服务器会使用 HTTP 响应标头来告知浏览器应该将资源缓存多长时间。如需了解详情,请参阅响应标头:配置 Web 服务器

HTTP 缓存策略和用例

HTTP 缓存比 Service Worker 缓存简单得多,因为 HTTP 缓存仅处理基于时间 (TTL) 的资源到期逻辑。如需详细了解 HTTP 缓存策略,请参阅您应该使用哪些响应标头值?摘要

设计缓存过期逻辑

本部分介绍了在 Service Worker 缓存和 HTTP 缓存层中使用一致的过期逻辑的优缺点,以及跨这些层的单独过期逻辑的优缺点。

以下故障演示了 Service Worker 缓存和 HTTP 缓存在不同场景中的实际运作方式:

所有缓存层均采用一致的过期逻辑

为了说明这些优缺点,我们将介绍 3 种场景:长期、中期和短期。

场景 长期缓存 中期缓存 短期缓存
Service Worker 缓存策略 缓存、回退到网络 重新验证时过时 网络回退到缓存
Service Worker 缓存 TTL 30 天 1 天 10 分钟
HTTP 缓存 max-age 30 天 1 天 10 分钟

场景:长期缓存(缓存、回退到网络)

  • 当缓存的资源有效时(不超过 30 天):Service Worker 会立即返回缓存的资源,而无需连接网络。
  • 当缓存的资源过期(超过 30 天)时:Service Worker 将连接到网络以提取资源。浏览器的 HTTP 缓存中没有资源的副本,因此会在服务器端转到服务器端获取资源。

缺点:在这种情况下,HTTP 缓存提供的值较少,因为当 Service Worker 中的缓存过期时,浏览器始终会将请求传递给服务器端。

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

  • 当缓存的资源有效时(不超过 1 天):Service Worker 会立即返回缓存的资源,并前往网络提取资源。浏览器在其 HTTP 缓存中拥有资源的副本,因此会将该副本返回给 Service Worker。
  • 当缓存的资源过期(超过 1 天)时:Service Worker 会立即返回缓存的资源,并前往网络提取资源。浏览器的 HTTP 缓存中没有资源的副本,因此会在服务器端提取资源。

缺点:Service Worker 需要额外的缓存无效化来替换 HTTP 缓存,以充分利用“重新验证”步骤。

场景:短期缓存(网络回退到缓存)

  • 当缓存的资源有效时(不超过 10 分钟):Service Worker 连接到网络以提取资源。浏览器在其 HTTP 缓存中拥有资源的副本,因此无需前往服务器端,即可将该资源的副本返回给 Service Worker。
  • 当缓存的资源过期(超过 10 分钟):Service Worker 会立即返回缓存的资源,并前往网络提取资源。浏览器的 HTTP 缓存中没有资源的副本,因此会在服务器端提取资源。

缺点:与中期缓存场景类似,Service Worker 需要额外的缓存无效化逻辑来替换 HTTP 缓存,以便从服务器端提取最新资源。

所有场景中的 Service Worker

在所有情况下,当网络不稳定时,Service Worker 缓存仍然可以返回缓存的资源。另一方面,当网络不稳定或关闭时,HTTP 缓存并不可靠。

Service Worker 缓存和 HTTP 层的缓存过期逻辑不同

为了说明这些方案的优缺点,我们将再次着眼于长期、中期和短期方案。

场景 长期缓存 中期缓存 短期缓存
Service Worker 缓存策略 缓存、回退到网络 重新验证时过时 网络回退到缓存
Service Worker 缓存 TTL 90 天 30 天 1 天
HTTP 缓存 max-age 30 天 1 天 10 分钟

场景:长期缓存(缓存、回退到网络)

  • 当缓存的资源在 Service Worker 缓存中有效时(<= 90 天):Service Worker 会立即返回缓存的资源。
  • 当 Service Worker 缓存中的缓存资源过期(超过 90 天)时:Service Worker 会连接到网络以提取资源。浏览器的 HTTP 缓存中没有资源的副本,因此会转到服务器端。

Pros and cons:

  • 优点:用户获享即时响应体验,因为 Service Worker 会立即返回缓存的资源。
  • 优点:Service Worker 可以更精细地控制何时使用其缓存以及何时请求新版本的资源。
  • 缺点:需要定义明确定义的 Service Worker 缓存策略。

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

  • 当缓存的资源在 Service Worker 缓存中有效时(<= 30 天):Service Worker 会立即返回缓存的资源。
  • 当 Service Worker 缓存中的缓存资源过期(超过 30 天)时:Service Worker 会转到网络寻找资源。浏览器在其 HTTP 缓存中没有资源的副本,因此会转到服务器端。

Pros and cons:

  • 优点:用户获享即时响应体验,因为 Service Worker 会立即返回缓存的资源。
  • 优点:由于“在后台”进行重新验证,Service Worker 可以确保给定网址的下一个请求使用来自网络的新响应。
  • 缺点:需要定义明确定义的 Service Worker 缓存策略。

场景:短期缓存(网络回退到缓存)

  • 当缓存的资源在 Service Worker 缓存中有效时(<= 1 天):Service Worker 会前往网络查找该资源。浏览器会从 HTTP 缓存中返回相应资源(如果有)。如果网络关闭,则 Service Worker 从 Service Worker 缓存中返回资源
  • 当 Service Worker 缓存中的缓存资源过期(超过 1 天)时:Service Worker 会转到网络提取资源。浏览器通过网络提取资源,因为其 HTTP 缓存中的缓存版本已过期。

Pros and cons:

  • 优点:当网络不稳定或关闭时,Service Worker 会立即返回缓存的资源。
  • 缺点:Service Worker 需要额外的缓存无效化来替换 HTTP 缓存并发出“网络优先”请求。

总结

鉴于缓存场景组合的复杂性,不可能设计一条覆盖所有情况的规则。但是,根据前面部分中的发现,我们在设计缓存策略时提供了一些建议:

  • Service Worker 缓存逻辑无需与 HTTP 缓存过期逻辑保持一致。如果可能,请在 Service Worker 中使用更长的失效逻辑,以向 Service Worker 授予更多控制权。
  • HTTP 缓存仍然发挥着重要作用,但在网络不稳定或宕机时并不可靠。
  • 重新访问每个资源的缓存策略,以确保 Service Worker 缓存策略提供其价值,而不会与 HTTP 缓存发生冲突。

了解详情