浏览器的缓存流程
强缓存 (Strong Caching)
原理:强缓存是一种直接从浏览器缓存中读取资源的策略,不需要向服务器发请求。即使资源更新,只要缓存未过期,浏览器也会直接使用缓存数据。
实现方法:
Expires:HTTP/1.0 标准,指定资源的过期时间。比如 Expires: Thu, 01 Dec 2024 16:00:00 GMT,表示资源在指定时间前缓存有效,但它受限于客户端时间设置(如果客户端时间不准确,缓存效果会受影响)。
Cache-Control:HTTP/1.1 标准,使用 max-age 来控制缓存时长。Cache-Control: max-age=31536000 表示资源在缓存中有效期为 31536000 秒(1年)。
Cache-Control的其他指令:
- public:资源客户端和服务器都可以缓存
- privite:资源只有客户端可以缓存
- no-cache:客户端缓存资源,但是是否缓存需要经过协商缓存来验证
- no-store:不使用缓存
注意:Cache-Control 比 Expires 更常用和可靠。当 Cache-Control 与 expires 两者都存在时,Cache-Control 优先级更高
优缺点:
优点:资源直接从缓存中读取,速度快且无需网络请求。
缺点:当资源更新时,客户端可能仍然使用旧版本,除非缓存失效(达到 max-age 或 Expires 时间)。
使用场景:
-
长期不会更新的静态资源:如图片、字体文件、第三方库的版本文件等。比如对某些版本的 jQuery 文件(如 jquery-3.5.1.min.js)可以设置较长的缓存周期,利用版本号区分文件版本。
-
前端资源的版本控制:可以通过文件名加入 hash 值或版本号来实现资源更新,这样每次文件变化都能生成新的文件名,避免加载旧的缓存。
协商缓存 (Conditional Caching)
原理:协商缓存是通过与服务器协商来决定是否使用缓存。每次请求都会发到服务器,服务器根据资源的状态决定是否使用缓存版本。协商缓存通常在资源有可能更新,但更新频率不高的情况下使用。
实现方法:
Last-Modified 和 If-Modified-Since:
Last-Modified:服务器在响应头中添加 Last-Modified,标记资源的最后修改时间。
If-Modified-Since:客户端在下次请求时带上 If-Modified-Since,告诉服务器上次缓存的时间。服务器会对比该时间与资源的最后更新时间: 如果资源没有修改,则返回 304 状态码,不传输数据,浏览器使用本地缓存。 如果资源已修改,返回新的资源内容和 200 状态码。
ETag 和 If-None-Match:
ETag:服务器为每个资源生成唯一标识符(ETag),通常是基于文件内容生成的 hash。
If-None-Match:客户端在下次请求时带上 If-None-Match,服务器根据 ETag 判断资源是否变化:
若 ETag 未变,则返回 304 状态码,客户端使用缓存。
若 ETag 改变,则返回新资源和 200 状态码。
为什么要有 Etag ?
Etag 的出现主要是为了解决一些 Last-Modified 难处理的问题:
- 一些文件也许会周期性的更改,但是内容并不改变(仅仅改变的修改时间),这时候并不希望客户端认为这个文件被修改了而重新去请求;
- 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说 1s 内修改了 N 次),If-Modified-Since 能检查到的粒度是秒级的,使用 Etag 就能够保证这种需求下客户端在 1 秒内能刷新 N 次 cache
注意:Etag 优先级高于 Last-Modified,若 Etag 与 Last-Modified 两者同时存在,服务器优先校验 Etag
优缺点:
优点:当资源更新时,浏览器自动获取最新资源,避免使用过期资源。
缺点:每次请求都会消耗一定的网络资源,虽无数据传输,但有一定请求时间。
使用场景:
-
经常更新但不频繁的资源:如 HTML、CSS 或 JavaScript 文件。这些文件通常会有一定的修改频率,但不会频繁变动,因此通过协商缓存可以较好地兼顾性能与更新。
-
不确定是否会变化的资源:比如接口数据、文档内容等资源可能会因业务调整而改变,但频率不可预测。
3、 强缓存与协商缓存的结合
实际中可以结合使用强缓存和协商缓存来实现更优的缓存策略。比如:
首次强缓存,过期后协商缓存:如设置 Cache-Control: max-age=86400,即强缓存1天,24小时后再与服务器进行协商缓存。如果文件有更新,协商缓存会自动获取最新版本,否则依然使用旧版本。
| 缓存策略 | 描述 | 适用场景 |
|---|---|---|
| 强缓存 | 直接从本地缓存读取,不请求服务器 | 静态资源、版本化文件 |
| 协商缓存 | 通过请求判断资源是否更新,未更新则使用缓存 | 不确定更新频率的资源,数据接口等 |
| 强+协商缓存 | 结合强缓存和协商缓存,减少请求次数并保证实时性 | 需要更新的资源,HTML、CSS等 |
通过合理的缓存策略配置,可以在确保页面性能的同时,保持资源内容的实时性,提升用户体验。