在 Service Worker 缓存层和 HTTP 缓存层中使用一致或不同的过期逻辑的优缺点。
虽然 service worker 和 PWA 正在成为现代 Web 应用的标准,但资源缓存也变得比以往更加复杂。本文将介绍浏览器缓存的概况,包括:
- Service Worker 缓存和 HTTP 缓存的使用情形和区别。
- 与常规 HTTP 缓存策略相比,不同 Service Worker 缓存过期策略的优缺点。
缓存流程概览
简要来说,浏览器在请求资源时会遵循以下缓存顺序:
- Service worker 缓存:Service worker 会检查资源是否位于其缓存中,并根据其已编程的缓存策略决定是否返回资源本身。请注意,此操作不会自动执行。您需要在服务工作线程中创建一个提取事件处理程序并拦截网络请求,以便从服务工作线程的缓存(而非网络)中提供请求。
- HTTP 缓存(也称为浏览器缓存):如果在 HTTP 缓存中找到资源且该资源尚未过期,浏览器会自动使用 HTTP 缓存中的资源。
- 服务器端:如果在 Service Worker 缓存或 HTTP 缓存中找不到任何内容,浏览器会前往网络请求资源。如果 CDN 中未缓存相应资源,请求必须一直回溯到源服务器。
缓存层
Service Worker 缓存
Service Worker 会拦截网络型 HTTP 请求,并使用缓存策略来确定应向浏览器返回哪些资源。Service Worker 缓存和 HTTP 缓存的总体用途相同,但 Service Worker 缓存提供更多缓存功能,例如可以精细控制缓存的具体内容和缓存方式。
控制 Service Worker 缓存
服务工作线程会通过事件监听器(通常是 fetch
事件)拦截 HTTP 请求。此代码段演示了先缓存缓存策略的逻辑。
强烈建议使用 Workbox,以免重复造轮子。例如,您可以使用一行正则表达式代码注册资源网址路径。
import {registerRoute} from 'workbox-routing';
registerRoute(new RegExp('styles/.*\\.css'), callbackHandler);
Service Worker 缓存策略和使用场景
下表概述了常见的 Service Worker 缓存策略以及每种策略的适用场景。
策略 | 新鲜度基本原理 | 用例 |
---|---|---|
仅限网络 | 内容必须始终保持最新状态。 |
|
网络回退到缓存 | 最好提供新内容。不过,如果网络出现故障或不稳定,提供略微过时的内容也是可以接受的。 |
|
过时重新验证 | 立即提供缓存内容是可以的,但未来应使用更新后的缓存内容。 |
|
先使用缓存,再回退到网络 | 内容不属于关键内容,可以从缓存中提供,以提高性能,但服务工作线程应偶尔检查更新。 |
|
仅缓存 | 内容很少会发生变化。 |
|
Service Worker 缓存的其他优势
除了对缓存逻辑进行精细控制之外,Service Worker 缓存还提供:
- 为来源提供更多内存和存储空间:浏览器会按来源分配 HTTP 缓存资源。换句话说,如果您有多个子网域,它们都会共享同一个 HTTP 缓存。无法保证您的来源/网域的内容在 HTTP 缓存中长时间保留。例如,用户可以通过以下方式清除缓存:在浏览器的设置界面中手动清理,或触发网页的硬重载。借助 Service Worker 缓存,缓存的内容更有可能保持缓存状态。如需了解详情,请参阅持久性存储。
- 在网络不稳定或离线体验方面具有更高的灵活性:使用 HTTP 缓存时,您只有两种选择:要么缓存资源,要么不缓存。借助 Service Worker 缓存,您可以更轻松地缓解小“故障”(使用“stale-while-revalidate”策略),提供完整的离线体验(使用“Cache only”策略),甚至提供介于两者之间的体验,例如自定义界面,其中部分网页内容来自 Service Worker 缓存,部分内容被排除在外(使用“Set catch handler”策略,在适当的情况下)。
HTTP 缓存
浏览器首次加载网页和相关资源时,会将这些资源存储在其 HTTP 缓存中。HTTP 缓存通常由浏览器自动启用,除非最终用户明确停用。
使用 HTTP 缓存意味着依赖服务器来确定何时缓存资源以及缓存多长时间。
使用 HTTP 响应标头控制 HTTP 缓存过期时间
当服务器响应浏览器对资源的请求时,服务器会使用 HTTP 响应标头告知浏览器应将资源缓存多长时间。如需了解详情,请参阅响应标头:配置 Web 服务器。
HTTP 缓存策略和应用场景
HTTP 缓存比 Service Worker 缓存简单得多,因为 HTTP 缓存仅处理基于时间 (TTL) 的资源过期逻辑。如需详细了解 HTTP 缓存策略,请参阅应使用哪些响应标头值?和总结。
设计缓存过期逻辑
本部分将介绍在 Service Worker 缓存和 HTTP 缓存层之间使用一致的过期逻辑的优缺点,以及在这些层之间使用单独的过期逻辑的优缺点。
针对所有缓存层采用了一致的过期逻辑
为了演示这两种方法的优缺点,我们将介绍 3 种情形:长期、中期和短期。
场景 | 长期缓存 | 中长期缓存 | 短期缓存 |
---|---|---|---|
Service Worker 缓存策略 | 缓存,回退到网络 | Stale-while-revalidate | 网络回退到缓存 |
Service Worker 缓存 TTL | 30 天 | 1 天 | 10 分钟 |
HTTP 缓存 max-age | 30 天 | 1 天 | 10 分钟 |
场景:长期缓存(缓存,回退到网络)
- 当缓存的资源有效(<= 30 天)时:服务工作线程会立即返回缓存的资源,而不会访问网络。
- 当缓存的资源过期(超过 30 天)时:服务工作器会前往网络来提取资源。浏览器在其 HTTP 缓存中没有相应资源的副本,因此会从服务器端获取该资源。
缺点:在此场景中,HTTP 缓存的价值较低,因为当服务工作线程中的缓存过期时,浏览器始终会将请求传递到服务器端。
场景:中长期缓存(过时后重新验证)
- 当缓存的资源有效(<= 1 天)时:服务工作线程会立即返回缓存的资源,并前往网络提取资源。浏览器在其 HTTP 缓存中存储了资源的副本,因此它会将该副本返回给服务工作器。
- 当缓存的资源过期(超过 1 天)时:服务工作线程会立即返回缓存的资源,然后前往网络提取资源。浏览器在其 HTTP 缓存中没有资源的副本,因此会转到服务器端来提取资源。
缺点:服务工作线程需要额外的缓存失效来替换 HTTP 缓存,以便充分利用“重新验证”步骤。
场景:短期缓存(网络回退到缓存)
- 当缓存的资源有效(<= 10 分钟)时:Service Worker 会前往网络来提取资源。浏览器在其 HTTP 缓存中存储了相应资源的副本,因此会将其返回给服务工作线程,而无需访问服务器端。
- 当缓存资源过期(超过 10 分钟)时:服务工作器会立即返回缓存资源,然后前往网络提取资源。浏览器在其 HTTP 缓存中没有资源的副本,因此会转到服务器端来提取资源。
缺点:与中长期缓存方案类似,服务工作线程需要额外的缓存失效逻辑来替换 HTTP 缓存,以便从服务器端提取最新资源。
所有场景中的服务工作线程
在所有场景中,当网络不稳定时,Service Worker 缓存仍可返回缓存的资源。另一方面,当网络不稳定或中断时,HTTP 缓存并不可靠。
Service Worker 缓存层和 HTTP 层的缓存过期逻辑不同
为了演示这些方法的优缺点,我们将再次考虑长期、中期和短期情景。
场景 | 长期缓存 | 中长期缓存 | 短期缓存 |
---|---|---|---|
Service Worker 缓存策略 | 缓存,回退到网络 | Stale-while-revalidate | 网络回退到缓存 |
Service Worker 缓存 TTL | 90 天 | 30 天 | 1 天 |
HTTP 缓存 max-age | 30 天 | 1 天 | 10 分钟 |
场景:长期缓存(缓存,回退到网络)
- 当缓存的资源在 Service Worker 缓存中有效(<= 90 天)时:Service Worker 会立即返回缓存的资源。
- 当服务工作线程缓存中的缓存资源过期(超过 90 天)时:服务工作线程会前往网络来提取资源。浏览器在其 HTTP 缓存中没有资源的副本,因此会转到服务器端。
Pros and cons:
- 优点:由于服务工作线程会立即返回缓存的资源,因此用户可以获得即时响应。
- 优点:Service Worker 可以更精细地控制何时使用其缓存,以及何时请求新版本的资源。
- 缺点:需要制定明确的 Service Worker 缓存策略。
场景:中期缓存(过时后重新验证)
- 当缓存的资源在 Service Worker 缓存中有效(<= 30 天)时:Service Worker 会立即返回缓存的资源。
- 当服务工作线程缓存中的缓存资源过期(超过 30 天)时:服务工作线程会前往网络获取资源。浏览器在其 HTTP 缓存中没有相应资源的副本,因此会转到服务器端。
Pros and cons:
- 优点:由于服务工作线程会立即返回缓存的资源,因此用户可以获得即时响应。
- 优点:借助“后台”重新验证,服务工作线程可以确保针对给定网址的下一个请求使用来自网络的最新响应。
- 缺点:需要制定明确的 Service Worker 缓存策略。
场景:短期缓存(网络回退到缓存)
- 当缓存的资源在 service worker 缓存中有效(<= 1 天)时:service worker 会前往网络获取资源。如果 HTTP 缓存中存在相应资源,浏览器会返回该资源。如果网络中断,服务工作线程会从服务工作线程缓存中返回资源
- 当服务工作线程缓存中的缓存资源过期(超过 1 天)时:服务工作线程会前往网络来提取资源。由于浏览器 HTTP 缓存中的缓存版本已过期,因此浏览器会通过网络提取资源。
Pros and cons:
- 优点:当网络不稳定或断开时,Service Worker 会立即返回缓存的资源。
- 缺点:服务工作线程需要额外的缓存失效来替换 HTTP 缓存并发出“先网络”请求。
总结
鉴于缓存方案组合的复杂性,无法设计出涵盖所有情况的规则。不过,根据前几部分中的发现,在设计缓存策略时,可以考虑以下几点建议:
- Service worker 缓存逻辑无需与 HTTP 缓存过期逻辑保持一致。如果可能,请在 Service Worker 中使用更长的过期逻辑,以授予 Service Worker 更多控制权。
- HTTP 缓存仍然发挥着重要作用,但在网络不稳定或中断时,它并不可靠。
- 重新检查每个资源的缓存策略,确保您的 Service Worker 缓存策略能发挥其价值,而不会与 HTTP 缓存发生冲突。