浏览器缓存机制

非HTTP协议定义的缓存机制

<meta http-equiv="Pragma" content="no-cache">  //告诉浏览器当前页面不被缓存

与缓存有关的HTTP头信息

请求、响应都有的头部

Cache-control:
        no-cache 告诉浏览器忽略资源的缓存副本,强制每次请求直接发送给服务器,拉取资源,但不是“不缓存”
        no-store 强制缓存在任何情况下都不要保留任何副本
        max-age=秒 指明缓存副本的有效时长,从请求时间开始到过期时间之间的秒数
        public 任何路径的缓存者(本地缓存、代理服务器),可以无条件的缓存该资源
        private 只针对单个用户或者实体(不同用户、窗口)缓存资源

响应头信息

Pragma:no-cache 
告诉浏览器忽略资源的缓存副本,每次访问都需要去服务器拉取。【http1.0中存在的字段,在http1.1已被抛弃,使用cache-control
替代,但为了做到http向下兼容,很多网站依旧会带上这个字段】

Expries:时间 
启用缓存和定义缓存失效时间。告诉浏览器缓存资源过期时间,如果还没过该时间则不发请求。【http1.0中的字段,是相对于服务器上
的时间而言的,如果客户端与服务器时间不一致,那就没意义了。HTTP1.1开始,使用cache-control:max-age=秒替代】

   
Last-Modified:时间  
告诉浏览器这个资源最后的修改时间。服务器将资源传递给客户端时,会将资源最后更改的时间以这个字段一起返回给客户端。
【只能精确到秒,如果某些文件在1秒之内被修改多次,将不能准确表示文件最后的修改时间】

ETag:唯一标识值  
告诉浏览器当前资源在服务器的唯一标识符(生成规则由服务器决定)

请求头部

If-Modified-Since:时间(上次响应头的Last-Modified值)  
值为上次响应头的Last-Modified值,再次向Web服务器请求时带上此头。【服务器收到请求后,将此时间与被请求资源的
最后修改时间进行比对。若最后时间较新,说明资源被改过,则响应整片资源内容(写在响应消息包体内),包括更新Last-Modified的值,
HTTP 200;若最后修改时间较旧,说明资源无更改,则响应HTTP 304(无需包体,节省浏览),告知浏览器继续使用所保存的cache】

If-None-Match:ETag值
当资源过期时(使用Cache-Control标识的max-age),发现资源具有ETag声明,则再次向web服务器请求时带上此头。web服务器收到请求后,
将此值与被请求资源的ETag进行比较,如果相同,就将If-None-Match的值设为false,返回状态为304,客户端继续使用本地缓存。客户端继续使用本地缓存决定返回200或304。

Last-Modified 和 If-Modified-Since
Last-Modified 表示本地文件最后修改日期,If-Modified-Since 会将 Last-Modified 的值发送给服务器,询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来。

但是如果在本地打开缓存文件,就会造成 Last-Modified 被修改,所以在 HTTP / 1.1 出现了 ETag 。

ETag 和 If-None-Match
ETag 类似于文件指纹,If-None-Match 会将当前 ETag 发送给服务器,询问该资源 ETag 是否变动,有变动的话就将新的资源发送回来。并且 ETag 优先级比 Last-Modified 高。

# 选择合适的缓存策略

Cache-Control与Expires的比较

   Cache-Control与Expires同时设置,则Cache-Control优先级更高。

Last-modified/ETag 与Cache-Control/Expires的比较

   配置Last-modified/ETag的情况下,浏览器再次访问统一URI的资源,还是会发送请求到服务器询问文件是否已经修改,如果没有,返回304,
   告知浏览器直接使用本地的缓存;如果修改过,那就整个数据重新发给浏览器。

   Cache-Control/Expires则不同,如果检测到本地的缓存还在有效时间内,浏览器直接使用缓存副本, 不会发送任何请求。

   两者一起使用时,Cache-Control/Expires的优先级要高于Last-modified/ETag。即当本地副本根据Cache-Control/Expires发现还在有
   效期内,则不会再次发送请求去服务器询问修改时间(Last-modified)或实体标识(ETag)了。

   一般情况下,使用Cache-Control/Expires会配合Last-modified/ETag一起使用,因为即使服务器设置缓存时间,当用户点击“刷新”按钮时
   ,浏览器会忽略缓存继续向服务器发送请求,这时Last-Modified/ETag将能够很好利用304,从而减少响应开销。

Last-modified 与 ETag的比较

Last-modified的几个问题:

ETag能够更加准确的控制缓存。

一起使用的时候,服务器会优先验证ETag,一致的情况下,再继续比对Last-modified,最后才决定是否返回304。

Last-Modified/If-Modified-Since,ETag/If-None-Match都要配合cache-control使用。

不能缓存的请求

用户行为与缓存

F5刷新:Expires/Cache-control过期时间会失效,但是Last-modified/ETag有效

ctrl + F5 /r 刷新:都无效,强制从服务器下载文件,响应200。

浏览器HTTP请求流程:

第一次请求:

图1

再次请求:

图2

是否过期:根据cache-control和Expires判断(cache-control优先)

==========================2018-07-02 新增==========

强制缓存与对比缓存

强制缓存

强制缓存:在缓存数据未失效的情况下,可以直接使用缓存数据。

对于强制缓存来说,响应header终会有两个字段来表明失效规则(expires【http1.0基本不再使用】/cache-control【http1.1】)

默认private //客户端可以缓存

max-age:xxx; //缓存内容将在xxx秒后失效

no-cache:需要使用对比缓存来验证缓存数据

对比缓存

需要进行比较来判断是否可以使用缓存

浏览器第一次请求数据时,服务器会将缓存标识与数据一起返回给客户端,客户端将二者备份至缓存数据库中。再次请求时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识来判断,判断成功后返回304响应(not modified),通知客户端比较成功,可以使用缓存数据。

ETag:存放缓存标识和If-Node-Match:ETag //再次请求时进行比较缓存标识

优先级高于

Last-Modified和If-Modified-Since

### 对于强制缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求直接使用缓存。不在时间内,执行比较缓存策略。

对于比较缓存,将缓存信息中的ETag和Last-modified通过请求发送给服务器,由服务器校验,返回304时,浏览器直接使用缓存。

Table of Contents