http缓存详解(强缓存协商缓存相关字段以及缓存流程解析)

Posted 过鹿人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了http缓存详解(强缓存协商缓存相关字段以及缓存流程解析)相关的知识,希望对你有一定的参考价值。

缓存相关字段:

http1.0:pragma、expires
http1.1:cache-control、last-modified、if-modified-since、etag、if-none-match

强缓存:

不发起http请求,直接使用本地缓存,比如浏览器地址栏回车,使用浏览器的刷新按钮,在Expires或max-age生效的情况下,触发强缓存。
不经常被修改的文件,通常用强缓存

协商缓存(弱缓存):

在使用本地缓存前,先与服务器协商,核对缓存文件是否为最新。请求头携带If-None-Match或If-Modified-Since,也可都携带。

 

一、Cache-control请求头/响应头

1.客户端设置

max-age:表示本地缓存的资源将在xx秒之后过期
no-cache:跳过强缓存和协商缓存阶段,直接请求服务器
no-store:不在本地缓存数据。

2.服务端设置

max-age:让客户端在xx秒内,不发起请求,直接使用本地缓存。(max-age=0相当于no-cache)
s-maxage: 覆盖max-age或者Expires头,但是仅适用于共享缓存(比如各个代理),私有缓存会忽略它。
no-cache:强制浏览器重新发送请求,但浏览器会缓存到本地。(不使用缓存)
no-store: 强制浏览器重新发送请求,并且禁止浏览器缓存数据。(不缓存)
public:响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存
private:响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。私有缓存可以缓存响应内容,比如:对应用户的本地浏览器。
must-revalidate:一旦资源过期(比如已经超过max-age),在成功向原始服务器验证之前,缓存不能用该资源响应后续请求。
immutable:响应正文不会随时间而改变。资源未过期,客户端不应发送重新验证请求头(例如If-None-Match或If-Modified-Since)来检查更新,即使用户显式地刷新页面。

 

二、Pragma 请求头/响应头

pragma:no-cache
http1.0使用的缓存字段,现在不常用,向后兼容只支持 HTTP/1.0 协议的缓存服务器,与 Cache-Control: no-cache 效果一致。

 

三、过期时间expires和cache-control:max-age

Expires: Thu, 29 Oct 2020 11:29:05 GMT 和 cache-control:max-age=10效果类似,max-age是相对时间,表示过了10s过后 再重新请求 而expires是绝对时间,表示过了这个时间,再重新请求。

1.首次请求

客户端:请求a.js文件
服务器:返回a.js + cache-control:max-age=10 + 过期时间Expires(Expires: Thu, 29 Oct 2020 11:29:05 GMT)
注意:expires主要是用来兼容http1.0版本的浏览器
 
如果在Cache-Control响应头设置了 "max-age" 或者 "s-max-age" 指令,那么 Expires 头会被忽略。

2.后续请求

客户端:
(1)先判断本地时间是否超过了过期时间,若时间没过,不发起请求,直接使用本地缓存。
(2)时间过期,重复步骤1
问题:
假设已过期,浏览器再次请求服务器,但a.js相比上次并未做任何改变,那这次请求我们是否通过某种方式加以避免?

 

四、Last-Modified(响应头)和if-Modified-Since(请求头)

同时设置cache-control:max-age和 last-modified表示强制缓存和协商缓存共用,若cache-control设置为max-age=0或者no-cache,则只有协商缓存生效

1.首次请求

客户端:请求a.js文件
服务器:返回a.js + cache-control:max-age=10 + last-modified(Thu, 22 Oct 2020 10:23:29 GMT) + 状态码200

2.后续请求

客户端:
(1)先判断本地时间是否超过了过期时间max-age,若未过期,使用浏览器缓存。
(2)过期,客户端带上if-Modified-Since(也就是上次请求服务器返回的Last-Modified),服务器将客户端传来的if-Modified-Since与自己的Last-Modified做对比。
(3)若if-Modified-Since ≠ Last-Modified,服务器返回新的a.js + 新的Last-Modified + cache-control:max-age=10
(4)若if-Modified-Since = Last-Modified,服务器返回状态码304,表示文件没修改过,让客户端使用浏览器的缓存。
 
问题:
1.资源文件每次一被修改,Last-Modified也会跟着修改,如果修改过后又进行版本回退,内容跟浏览器已缓存的一致,但用户还是要重新请求资源,因为Last-Modified改变了。

2.Last-Modified只能精确到秒,如果恰好在一秒之内变化了,Last-Modified是不会修改成功的。
 
 

五、Etag(响应头)和if-None-Match(请求头)

服务端生成资源文件的唯一标识符Etag,资源更改,则一定要生成新的Etag值
对于大文件,不会根据整个文件去生成hash 可以使用文件大小或者文件开头去生成hash

md5是 摘要算法,也叫hash算法
1. 是单向的 无法反解
2. 对于相同内容 加密结果相同;不同的内容 加密结果的长度相同

1.首次请求

客户端:请求a.js文件

服务器:返回a.js + cache-control:max-age=10 + last-modified(Thu, 22 Oct 2020 10:23:29 GMT) + Etag + 200

2.后续请求

客户端:

(1)先判断本地时间是否超过了过期时间max-age,未过期,则使用浏览器缓存。

(2)若过期,客户端带上if-Modified-Since + if-None-Match,服务器先将客户端传来的if-None-Match与自己的Etag做对比。

(3)若if-None-Match ≠ Etag 服务器返回新的a.js + 新的Etag + Last-Modified + cache-control:max-age=10

(4)若if-None-Match = Etag,服务器返回状态码304,表示文件没修改过,让客户端使用浏览器的缓存,if-Modified-Since和Last-Modified 也不需要再比较了。

面试点睛:

为什么有了Last-Modified还要用etag?

1. 防止Last-Modified变了,但文件内容没变的情况下,浏览器需要重新请求服务器
2. 防止文件在1s内发生变化,而Last-Modified不变

 

以上是关于http缓存详解(强缓存协商缓存相关字段以及缓存流程解析)的主要内容,如果未能解决你的问题,请参考以下文章

HTTP学习彻底弄懂 Http 缓存机制 - 浏览器缓存机制详解

基于Nginx设置浏览器协商缓存过程详解

前端技能树,面试复习第 38 天—— 浏览器原理:详解浏览器缓存机制 | 协商缓存与强缓存(重点)

HTTP之强缓存和协商缓存

协商缓存和强缓存的区别

HTTP进阶,实战剖析强缓存和协商缓存!