Service workers 和 Cache Storage API

您正深陷于网络可靠性的斗争中。浏览器的 HTTP 缓存是您的第一道防线,但正如您所了解的,它仅在加载您之前访问过的版本化网址时才真正有效。仅靠 HTTP 缓存是不够的。

幸运的是,现在有两个较新的工具可以帮助您扭转局面:service workersCache Storage API。由于它们经常一起使用,因此值得同时了解它们。

Service workers

Service worker 内置于浏览器中,并由您负责创建的一小段额外 JavaScript 代码控制。您可以将其与构成实际 Web 应用程序的其他文件一起部署。

Service worker 具有一些特殊功能。除其他职责外,它还会耐心地等待您的 Web 应用程序发出传出请求,然后通过拦截该请求而立即采取行动。Service worker 如何处理此拦截的请求取决于您。

对于某些请求,最佳做法可能只是允许请求继续到网络,就像在根本没有 service worker 的情况下会发生的情况一样。

但是,对于其他请求,您可以利用比浏览器 HTTP 缓存更灵活的东西,并返回可靠快速的响应,而无需担心网络。这需要使用难题的另一部分:Cache Storage API。

Cache Storage API

浏览器支持

  • Chrome: 43.
  • Edge: 16.
  • Firefox: 41.
  • Safari: 11.1.

来源

Cache Storage API 通过让开发者完全控制缓存内容,开辟了一系列全新的可能性。Cache Storage API 没有依赖 HTTP 标头和浏览器的内置 启发式方法 的组合,而是公开了一种代码驱动的缓存方法。当从您的 service worker 的 JavaScript 中调用时,Cache Storage API 特别有用。

等等……现在还有另一个缓存需要考虑?

您可能会问自己诸如“我是否仍然需要配置我的 HTTP 标头?”和“对于 HTTP 缓存无法实现的功能,我可以使用这个新缓存做什么?”之类的问题。别担心,这些都是自然的反应。

即使您知道自己正在使用 Cache Storage API,仍然建议您在 Web 服务器上配置 Cache-Control 标头。对于未版本化的网址,您通常可以设置 Cache-Control: no-cache,对于包含版本控制信息(如哈希)的网址,您可以设置 Cache-Control: max-age=31536000

在填充 Cache Storage API 缓存时,浏览器 默认检查 HTTP 缓存中是否已存在条目,如果找到则使用这些条目。如果您要将版本化的网址添加到 Cache Storage API 缓存,则浏览器会避免额外的网络请求。反之,如果您使用配置错误的 Cache-Control 标头(例如,为未版本化的网址指定长期缓存生存期),您最终可能会通过将过时的内容添加到 Cache Storage API 中而 使情况变得更糟。整理好 HTTP 缓存行为是有效使用 Cache Storage API 的先决条件。

至于现在使用这个新 API 可以实现什么,答案是:很多。仅使用 HTTP 缓存难以或不可能实现的一些常见用途包括

  • 对缓存内容使用“在后台刷新”方法,也称为“陈旧内容再验证”。
  • 对要缓存的资产的最大数量施加限制,并实施自定义过期策略以在达到该限制后删除项目。
  • 比较以前缓存的和新的网络响应,以查看是否有任何更改,并在数据实际更新时使用户能够更新内容(例如,使用按钮)。

查看 Cache API:快速指南 以了解更多信息。

API 实质

关于 API 的设计,需要记住以下几点

  • Request 对象用作在这些缓存中读取和写入时的唯一键。为了方便起见,您可以传入 URL 字符串(如 'https://example.com/index.html')作为键,而不是实际的 Request 对象,API 会自动为您处理。
  • Response 对象用作这些缓存中的值。
  • 在缓存数据时,给定 Response 上的 Cache-Control 标头实际上被忽略。没有自动的内置过期或新鲜度检查,一旦您将项目存储在缓存中,它将一直存在,直到您的代码显式删除它。(有一些库可以代表您简化缓存维护。它们将在本系列的后面部分介绍。)
  • 与较旧的同步 API(如 LocalStorage)不同,所有 Cache Storage API 操作都是异步的。

快速绕道:promise 和 async/await

Service worker 和 Cache Storage API 使用 异步编程概念。特别是,它们严重依赖 promise 来表示异步操作的未来结果。在深入了解之前,您应该熟悉 promise 以及相关的 async/await 语法。

暂时不要部署该代码……

虽然 service worker 和 Cache Storage API 提供了重要的基础,并且可以按原样使用,但它们实际上是较低级别的构建块,存在许多边缘情况和“陷阱”。有一些更高级别的工具可以帮助简化这些 API 的困难部分,并提供构建生产就绪 service worker 所需的一切。下一篇指南介绍了这样一种工具:Workbox