HTTP缓存分为两种,强缓存与协商缓存,先来看几张HTTP请求的截图:
可以发现请求头/响应头里一些有意思的属性:ETag、Last-Modified、Expires、Cache-Control、Pragma、If-None-Match、If-Modified-Since等,这些都与HTTP缓存有关系
强缓存
Expires / Cache-Control
Expires是HTTP1.0中的强缓存机制,是一个绝对值时间。
Cache-Control是HTTP/1.1中出现的强缓存机制,是一个相对值时间。
所以当两者同时出现时,以Cache-Control优先。因为Expires是绝对值时间,客户端与服务端时间可能存在误差,所以相对于Cache-Control来说,Expires准确率没那么高。
当浏览器第一次去服务器请求数据时,服务器返回数据,响应头Date属性有此请求的时间 Mon, 22 Mar 2021 06:17:00 GMT
若服务器希望此次HTTP缓存30秒有效,则响应头中可如下设置
Expires:Mon, 22 Mar 2021 06:17:30 GMT
Cache-Control:max-age=30
当浏览器再次发起请求,浏览器通过检查本地缓存的数据,若未过期,则不需向服务器发起请求,直接使用本地的缓存数据,此时HTTP状态码为200(from memory cache / from disk cache)从内存中读取数据或从硬盘中读取数据
cache-control的其他属性:https://baike.baidu.com/item/Cache-control/1885913
Pragma
Pragma是HTTP/1.0中的缓存机制,用来向后兼容,算是时代的旧产物,快被抛弃了。
Pragma:no-cache 与 cache-control:no-cache 作用相同
当两者同时出现时,Pragma优先级更高
协商缓存
协商缓存通常一对一对配合使用,ETag与If-None-Match是一对,Last-Modified与If-Modified-Since是一对。
ETag / If-None-Match
当浏览器第一次进行请求时,响应头返回ETag标识资源的唯一值(当资源发送变化,这个值会变)
当浏览器再次进行请求,强缓存又没有命中的情况,浏览器会向服务器发起请求,并在请求头中携带上次请求缓存的ETag值,放在If-None-Match中。
例如第一次请求,响应头返回
ETag:48472445140208031
再次请求,强缓存没有命中,则发起请求的请求头携带
If-None-Match:48472445140208031
服务端根据请求的If-None-Match判断是否命中缓存,如果资源没有变化,则值相同,返回HTTP状态 304,浏览器从本地缓存中取值。如果资源被修改,etag值发生变化,则返回HTTP状态码200,新的资源和新的ETag值
Last-Modified / If-Modified-Since
这对协商缓存情侣与上对相比,是通过资源的最后一次修改时间来判断缓存是否命中。
有以下两个缺点:
- 只要编辑了,不管内容是否真的有改变,都会以这最后修改的时间作为判断依据,当成新资源返回,从而导致了没必要的请求响应,而这正是缓存本来的作用即避免没必要的请求。
- 时间的精确度只能到秒,如果在一秒内的修改是检测不到更新的,仍会告知浏览器使用旧的缓存。
请求过程与上对情侣类似。如果两对协商缓存情侣同时存在,以ETag优先进行比对