1. 强缓存
给浏览器缓存设置过期时间,超过这个时间之后缓存过期,浏览器需要重新请求。
expires(老版本http1.0)
给浏览器设置了一个绝对时间用GMT格式的字符串,当浏览器时间超过这个绝对时间之后,重新向服务器发送请求。如下:
Expires: Wed Feb 20 2019 11:25:41 GMT
弊端: Expires返回的是服务器的时间,但判断的时候用的却是客户端的时间,这就导致Expires很被动,因为用户有可能改变客户端的时间,导致缓存时间判断出错,这也是引入Cache-Control:max-age指令的原因之一。
cache-control(http1.1)
为了解决expires存在的问题,Http1.1版本中提出了cache-control:max-age,该字段与expires的缓存思路相同,都是设置了一个过期时间,不同的是max-age设置的是相对缓存时间开始往后的多少秒
,因此不再受日期不准确情况的影响。
常见的值是max-age
public private no-cache
no-store
- cache-control: max-age=xxxx,public。
客户端和代理服务器都可以缓存该资源;客户端在xxx秒的有效期内,如果有请求该资源的需求的话就直接读取缓存,statu code:200 ,如果用户做了刷新操作,就向服务器发起http请求 - cache-control: max-age=xxxx,private
只让客户端可以缓存该资源;代理服务器不缓存
客户端在xxx秒内直接读取缓存 - cache-control: max-age=xxxx,immutable。
客户端在xxx秒的有效期内,如果有请求该资源的需求的话就直接读取缓存,statu code:200 ,即使用户做了刷新操作,也不向服务器发起http请求 - cache-control: no-cache
跳过设置强缓存,但是不妨碍设置协商缓存;一般如果做了强缓存,只有在强缓存失效了才走协商缓存的,设置了no-cache就不会走强缓存了,每次请求都回询问服务端。 - cache-control: no-store
不缓存,这个会让客户端、服务器都不缓存,也就没有所谓的强缓存、协商缓存了。
强缓存弊端: 强缓存优先级高,如果在过期时间内缓存的资源在服务器上更新了,客服端不能及时获取最新的资源。这时怎么办?于是就有了协商缓存.
2. 协商缓存
协商缓存解决了无法及时获取更新资源的问题。它利用【Last-Modified,If-Modified-Since】
、【ETag、If-None-Match】
两组字段,对资源做标识.然后由服务器做分析,如果资源未更新,则返回304状态码.那么浏览器则会从缓存中读取资源,否则重新请求资源。
1). Last-Modified与If-Modified-Since
浏览器第一次向服务器请求资源
,服务器会在返回这个资源的同时,在response的header加上Last-Modified
的header,这个header表示这个资源在服务器上的最后修改时间:Last-Modified: Wed Feb 20 2021 14:08:32 GMT浏览器之后(第2次+)再向服务器请求这个资源时
,在request的header上加上If-Modified-Since
的header,这个header的值就是上一次请求时返回的Last-Modified的值服务器再次(第2次+)收到资源请求时
,根据浏览器传过来If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回304 Not Modified,但是不会返回资源内容
;如果有变化,返回200,就正常返回资源内容。- 浏览器收到304的响应后,就会从缓存中加载资源。(当服务器返回304 Not Modified的响应时,response的header中不会再添加Last-Modified的header,因为既然资源没有变化,那么Last-Modified也就不会改变,这是服务器返回304时的response header.)
- 浏览器收到200的响应后,则从服务器加载新资源时,Last-Modified Header在重新加载的时候会被更新,下次请求时,If-Modified-Since会启用上次返回的Last-Modified值。
弊端:
由于是根据服务器最后修改时间
返回的header
- 它们是以秒为单位进行更新,如果小于该单位高频进行更新的话,则不适合采用该方法。
- 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新get;
- 某些服务器不能精确的得到文件的最后修改时间。
2). ETag与If-None-Match
浏览器第一次跟服务器请求一个资源
,服务器在返回这个资源的同时,在response的header加上ETag
的header,这个header是服务器根据当前请求的资源生成的一个唯一标识字符串,如ETag:baitedangsi,只要资源有变化这个串就不同,跟最后修改时间没有关系
,所以能很好的补充Last-Modified的问题.浏览器再次(第二次+)跟服务器请求这个资源时
,在request的header上加上If-None-Match
的header,这个header的值就是上一次请求时返回的ETag的值。服务器再次(第二次+)收到资源请求时
,根据浏览器传过来If-None-Match
和服务器根据资源生成一个新的ETag
对比,如果这两个值相同就说明资源没有变化,否则就是有变化;如果没有变化则返回304 Not Modified,但是不会返回资源内容
;如果有变化,则返回200,并正常返回资源内容。与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化- 浏览器收到304的响应后,就会从缓存中加载资源。
- 浏览器收到200的响应后,则从服务器加载新资源时,
ETag在重新加载的时候会被更新
,下次请求时,If-None-Match会启用上次返回的ETag值。
优先级:
ETag与If-None-Match > Last-Modified与If-Modified-Since, 同时存在时, 前者覆盖后者.