您陷入了网络可靠性的困境。浏览器的 HTTP 缓存是您的第一道防线,但正如您所了解的,只有当您加载您之前访问过的带版本号的网址时,它才有效。HTTP 缓存本身是不够的。
幸运的是,有两个新的工具可以帮助您扭转局势:Service Worker 和 Cache Storage API。由于这两种视图经常一起使用,因此值得同时了解它们。
Service Worker
Service Worker 内置于浏览器中,并由您负责创建的一些额外 JavaScript 代码控制。您需要将此文件与构成实际 Web 应用的其他文件一起部署。
Service Worker 拥有一些特殊的能力。其职责包括,耐心等待您的 Web 应用发出传出请求,然后通过拦截它来跳入行动。Service Worker 如何处理这一被拦截的请求由您决定。
对于某些请求,最好的操作是允许请求继续传送到网络,就像根本没有 Service Worker 会发生这种情况一样。
但是,对于其他请求,您可以利用比浏览器的 HTTP 缓存更加灵活的功能,并返回可靠且快速的响应,而无需担心网络问题。为此,我们需要使用另外一个谜题:Cache Storage API。
Cache Storage API
Cache Storage API 让开发者可以完全控制缓存内容,从而开辟了全新的可能性范围。Cache Storage API 采用代码驱动型缓存方法,而不是依赖于 HTTP 标头和浏览器内置heuristics的组合。从 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 来使情况变差。若要有效使用 Cache Storage API,必须先对 HTTP 缓存行为进行排序。
至于此新 API 可以实现的功能,答案是:很多。仅使用 HTTP 缓存很难或不可能实现的一些常见用途包括:
- 对缓存的内容使用“在后台刷新”方法,称为过时同时重新验证。
- 对要缓存的资产数上限施加限制,并实现自定义到期政策,以便在达到该限制时移除项。
- 比较之前缓存的响应和新的网络响应,以查看是否有任何更改,并让用户能够在实际更新数据后更新内容(例如,使用按钮)。
如需了解详情,请参阅 Cache API:快速指南。
API 螺母和螺栓
关于该 API 的设计,请注意以下几点:
- 在读取和写入这些缓存时,
Request
对象会用作唯一键。为方便起见,您可以将'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。