前端http请求细节——Cache-Control(缓存机制)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端http请求细节——Cache-Control(缓存机制)相关的知识,希望对你有一定的参考价值。

参考技术A

请求和响应中的 Cache-Control 指令并不完全相同,具体可以查看 这里 ,包括指令的具体意思,这里不过多赘述。(默认值:private)

浏览器的缓存机制是根据 HTTP 报文的缓存标识进行的,浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中 HTTP 头的缓存标识,决定是否缓存结果。
浏览器缓存策略分为两种:强制缓存和协商缓存。

强制缓存不会向服务器发送请求,直接从缓存中读取资源,可以看到请求返回的状态码都是200,并且 Size 代表该缓存的位置。

浏览器读取缓存的顺序为memory –> disk。

三级缓存原理 (访问缓存优先级):

在浏览器中,浏览器会在js,字体,图片等文件解析执行后直接存入内存缓存中,那么当刷新页面时只需直接从内存缓存中读取(from memory cache);而css文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘读取缓存(from disk cache)。

为什么CSS会放在硬盘缓存中?
因为CSS文件加载一次就可渲染出来,我们不会频繁读取它,所以它不适合缓存到内存中,但是js之类的脚本却随时可能会执行,如果脚本在磁盘当中,我们在执行脚本的时候需要从磁盘取到内存中来,这样IO开销就很大了,有可能导致浏览器失去响应。

若服务器的资源最后被修改时间 > If-Modified-Since的字段值
则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件

If-None-Match 的字段值 = 该资源在服务器的Etag值
一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200。

ETag 和 Last-Modified 区别

参考链接:
https://juejin.im/entry/5ad86c16f265da505a77dca4
https://www.cnblogs.com/suihang/p/12855345.html
https://www.jianshu.com/p/54cc04190252

HTTP之缓存 Cache-Control

通过在Response Header设置Cache-Control head 信息可以控制浏览器的缓存行为。

我们先来看一下Cache-Control可以设置哪些值:

一、可缓存性

  public: http通信的过程中,包括请求的发起方(浏览器)、代理缓存服务器都可以进行缓存。

  private :只允许请求的发起方(浏览器)进行缓存。

  no-cache:可以在请求的发起方(浏览器)进行缓存,但是每次都需要去服务器进行资源验证。

  no-store:任何地方都不可以缓存。

二、到期

  max-age:<seconds> 表示缓存多少秒之后过期(浏览器和代理缓存服务器中都是),如果只设置了max-age,没有设置no-cache,浏览器在要请求相同的静态文件时,会看是否在max-age时间内,如果在的会就直接使用缓存中的值了,单独只设置max-age很可能会造成资源得不到及时的更新。

  s-maxage:<seconds>表示代理缓存服务器中的静态资源多少秒之后过期,如果同时设置了max-age和s-maxage,在浏览器中,使用max-age进行判断,在代理缓存服务器中使用s-maxage进行判断。

三、重新验证

  must-revalidate:缓存(浏览器和代理缓存服务器中都是)过期后必须去重新验证。

  proxy-revalidate:代理缓存服务器中缓存过期后必须去验证。

浏览器发起请求时与缓存相关的步骤:

技术图片

发起方发起请求后,先去本地缓存中查找,命中就返回给发起方,不命中的话就去代理缓存服务器中查找,命中就返回,不命中才会去源服务器查找。

 需要清楚的是,缓存头Cache-Control只能在服务端设置,在客户端是由浏览器设置的,自己不能修改它的值。

下面说明几种情况:

一、如果单独使用max-age,在缓存有效的时间内浏览器对相同的资源发起请求是得不到更新的、为了解决这个问题,可以在每次编译时给静态文件设置hash值,这样,在浏览器再次对静态资源发起请求时,资源的名称已经修改了,浏览器不会认为是同一资源,也就不会去缓存中寻找,直接去源服务器中获取。

二、如果设置了no-cache,在缓存有效的时间内,浏览器对相同的资源发起请求时,会先去服务器询问资源是否修改过,资源没有修改时,响应304 Not Modified,浏览器得到304响应后,判断缓存可以使用,就会直接使用缓存。如果资源更新过,就返回200,浏览器使用返回的资源。

当设置了no-cache时,需要有一种验证机制来判断资源是否更新过:

  1. Last-Modified配合If-Modified-Since或者If-Unmodified-since使用:对比上次修改时间来验证是否使用缓存。步骤是:client第一次对资源发起请求时,server会设置Last-Modified的头信息,当浏览器再次对相同的资源发起请求时,浏览器会设置request的头部(chrome可以使用disable cache来禁止浏览器自动设置,这样每次都会去源服务器获取),设置If-Modified-Since或者If-Unmodified-since的值为之前接收到的Last-Modified的值,这样,server每次取得头部信息If-Modified-Since或者If-Unmodified-since,与文件的修改时间进行对比,如果相同,就返回304Not Modified,client使用缓存,如果不相同,就返回更新后的资源。
  2. Etag 数字签名配合If-Match或者If-None-Match使用:一般的数字签名可以对资源的内容进行hash计算,client第一次请求资源时,在server中设置头部信息Etag,值为hash值,当浏览器再次对相同的资源发起请求时,浏览器会设置request的头部,设置If-Match或者If-None-Match的值为之前接收到的Etag的值,这样,server每次取得头部信息If-Match或者If-None-match,与重新计算的hash值进行对比,如果相同,就返回304Not Modified,client使用缓存,如果不相同,就返回更新后的资源。

以上是关于前端http请求细节——Cache-Control(缓存机制)的主要内容,如果未能解决你的问题,请参考以下文章

node实战前端缓存总结

前端HTTP缓存

前端关于浏览器缓存设置

HTTP之缓存 Cache-Control

前端面试题

前端应该懂的浏览器缓存策略