前端缓存之HTTP缓存

Web 缓存大致可以分为:数据库缓存、服务器端缓存(代理服务器缓存、CDN 缓存)、浏览器缓存

浏览器缓存http缓存、indexDB、cookie、localstorage 等。

本次我们重点理解http缓存相关问题。

http缓存,主要分为强缓存协商缓存

1、浏览器加载一个页面资源的简单流程为:

  1. 浏览器根据这个资源的http头信息来判断是否命中强缓存,如果命中强缓存就直接加载在缓存中的资源,并且不会讲请求发送到服务端。(强缓存)
  2. 如果没有命中强缓存,则浏览器会将资源加载请求发送到服务器,服务器来判断浏览器本地缓存是否失效,如果可以使用,浏览器是不会返回资源信息的,而是让浏览器继续从缓存加载资源。(协商缓存,又称弱缓存)
  3. 如果没有命中协商缓存,则服务器会将完整的资源返回给浏览器,浏览器加载新资源并更新缓存。(新的请求)
    前端缓存之HTTP缓存

2、强缓存

命中强缓存时,浏览器的请求是不会发送到服务器的,在chrome 浏览器开发者工具可以看到http请求返回码是200,size值则显示为from cache
前端缓存之HTTP缓存
强缓存实现:利用http返回头中的Expires或Cache-Control两个字段来控制的,表示资源的缓存时间。

  • Expires

含义: 表示缓存的过期时间,用来指定资源到期的时间,是服务端的具体时间点。

示例: Expires: Tue, 31 Dec 2037 23:59:59 GMT 代表在2037年12月31号23点59分59秒前,这个资源都是有效的。

缺点: Expires设置的时间是一个绝对时间,所以如果客户端本地的时间修改了,服务端与客户端的时间不同步,从而导致缓存混乱。

  • Cache-Control

含义: 表示资源的有效时间,是一个相对时间。

示例: Cache-Control:max-age=3000 表示缓存有效期为(3153600/24/60*60)天

取值: 可以由多个字段组合。具体字段如下:

max-age: 指定一个时间长度,在这个时间段内缓存是有效的,单位是s。例如设置 Cache-Control:max-age=31536000,也就是说缓存有效期为(31536000 / 24 / 60 * 60)天,第一次访问这个资源的时候,服务器端也返回了 Expires 字段,并且过期时间是一年后。前端缓存之HTTP缓存

s-maxage: 同 max-age,覆盖 max-age、Expires,但仅适用于共享缓存,在私有缓存中被忽略。
public: 表明响应可以被任何对象(发送请求的客户端、代理服务器等等)缓存。
private: 表明响应只能被单个用户(可能是操作系统用户、浏览器用户)缓存,是非共享的,不能被代理服务器缓存。
no-cache: 强制所有缓存了该响应的用户,在使用已缓存的数据前,发送带验证器的请求到服务器。
no-store: 禁止缓存,每次请求都要向服务器重新获取数据。

  • Cache-Control 优先级高于 Expires。

3、协商缓存

如果没命中强缓存,浏览器会将http请求发送到服务器,服务器根据http头信息中的Last-Modify/If-Modify-Since或Etag/If-None-Match来判断是否命中协商缓存。

  • Last-modified / If-Modified-Since

Last-modified:服务器端资源的最后修改时间,响应头部会带上这个标识。
例如:Sun Apr 25 2021 11:09:15 GMT,表示最后一次修改该资源的时间是2021年4月25好12点59分59秒。
前端缓存之HTTP缓存

浏览器第一次请求一个资源的时候,服务端返回的header中会加上Last-modified,标识该资源的最后修改时间。

当浏览器再次请求该资源时,发送的请求头中会包含If-Modified-Since,这个值就是上一次返回的Last-modified的值,服务端收到If-Modified-Since后会去对比资源的最后修改时间来判断是否命中缓存。

若命中缓存,则状态码返回304,并且不会返回资源内容,并且不会返回Last-modified字段。否则就返回最新资源,状态码 200。

注意: 如果响应头中有 Last-modified 而没有 Expire 或 Cache-Control 时,浏览器会有自己的算法来推算出一个时间缓存该文件多久,不同浏览器得出的时间不一样,所以 Last-modified 要记得配合 Expires/Cache-Control 使用。

  • Etag / If-None-Match

Etag / If-None-Match返回的事一个校验码(Etag:entity tag)。Etag的值变化了则说明资源状态被修改了,服务的就根据浏览器发送的If-None-Match值来匹配是否命中缓存。
前端缓存之HTTP缓存
Etag可以保证每个资源是唯一的,资源变化一定导致Etag变化。Etag生成或变化的因子有:
a) 文件的i-node编号,指Linux/Unix用来识别文件的编号,使用ls -l可查看;
b) 文件最后的修改时间;
c) 文件大小。

Etag是服务器自动生成,或者由开发者生成的对应资源在服务的唯一标识符,属于强验证,要求资源字节级别的一致,能够更加准确的控制缓存,Last-Modified和Etag一起使用时,服务器会优先校验Etag,Etag一致的情况下,才会继续对比Last-Modified最后决定是否返回304.

注意: 计算 ETag 也是需要占用资源的,如果修改不是过于频繁,看需求用 Cache-Control 是否可以满足。

  • 问:为什么有了Last-Modified还要Etag?

1)Last-modified 标注的最后修改时间只能精确到秒。如果某些文件在1秒以内被修改多次,就不能准备标注文件的修改时间。

2)一些资源的最后修改时间改变了(例如某些文件被定期生成),Last-modified也更着改变了,但是内容实际并没有改变,导致文件不能使用缓存。

3)如果只有Last-modified ,就有可能存在服务器没有准确获取文件修改的时间,或者与代理服务器时间不一致的情形。

上一篇:git学习2 -时光穿梭


下一篇:前端小白学习web缓存笔记