HTTP缓存/浏览器缓存

浏览器缓存就是把已经请求过的web资源拷贝一份副本存储在浏览器中,第二次请求时会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。

浏览器对于缓存的处理是根据第一次请求资源时返回的响应头来确定的也就是Response Headers

强缓存

  • 左图为已经有缓存数据的情况:缓存未失效,直接使用缓存数据

    表现为: Status Code: 200 (from memory cache) 或 (from disk cache )

  • 右图为缓存数据失效的情况:向源服务器请求数据,将数据和缓存规则存入缓存(一般为浏览器内存或磁盘中)

那么问题来了,浏览器怎么知道缓存是否失效呢?

根据响应头里的 Expires 和 Cache-Control 来判断

  • Expires 是HTTTP1.0版本定义的缓存字段,值为服务器端返回的到期时间(绝对时间),如果客户端的时间与服务器端的时间有误差,会导致缓存命中的误差。
  • Cache-Control 是HTTP1.1版本定义的缓存字段
意义
private 客户端可以缓存
public 客户端和代理服务器可以缓存
max-age=xxx 缓存在xxx秒后失效
no-cache 需要使用协商缓存来验证缓存数据
no-store 不缓存

Expires和Cache-Control同时存在时Cache-Control值为max-aga=xxxx 会直接忽略Expires 。 `

上图可以看到,从浏览器内存中返回的数据,并没有向源服务器返回数据

Cache-Control对应的是2592000s以后缓存失效,也就是30天内请求这个url都直接从浏览器缓存中得到数据。

Expires: 2018年8月22日07:23:08过期

按照之前说的 Expires会被忽略

协商缓存

  • 左图为缓存未失效时,先向缓存得到Etag或者Last-Modified,然后请求服务器Request Headers会带上If-None-Match(值就是上一次请求返回的Etag 唯一标识) 或If-Modified-Since (上一次请求返回的资源最后修改时间), 服务器收到If-None-Match 与唯一标识对比,没有改变 或 If-Modified-Since 与资源最后修改时间对比,没有改变,即响应HTTP 304告诉浏览器使用浏览器缓存。浏览器直接从缓存里拿到数据。
  • 右图之前的步骤同上,但If-None-Match 与资源唯一标识不同 或 If-Modified-Since小于资源最后修改时间,则表示缓存的资源已经失效,返回状态码 200 并且返回最新的数据,浏览器缓存数据。

通过上面的分析可以看出

协商缓存:是根据响应头中的EtagLast-Modified以及请求头中的If-None-MatchIf-Modified-Since 字段来判断是否过期。

缓存规则优先级及生效情况:

  • 强缓存与协商缓存同时存在,如强缓存还在生效期,强缓存覆盖协商缓存;
  • 强缓存的expires和cache-control同时存在,则cache-control覆盖;
  • 协商缓存Etag和Last-Modified同时存在时,Etag覆盖Last-Modified;

服务器配置http缓存(nginx为例)

1
2
3
4
5
location ~ .*\.(js|css)$ {
expires 1d;
add_header Cache-Control max-age=315360000;
}
#nginx中Last-Modified 和 Etag是默认打开的

以上配置可以对应请求的响应头

常见的HTTP请求头及响应头

请求头字段 说明 示例
Accept 可接受的响应内容类型 Accept: application/json
Accept-Encoding 可接受的响应内容的编码方式 Accept-Encoding: gzip, deflate
Accept-Charset 可接受的字符集 Accept-Charset: utf-8
Accept-Language 可接受的响应内容语言列表 Accept-Language: zh-CN,zh;q=0.9
Authorization 用于表示HTTP协议中需要认证资源的认证信息 Authorization: Basic OSdjJGRpbjpvcGVuIANlc2SdDE==
If-None-Match 设置客户端ETag,如果和服务端接受请求生成的ETage相同,允许服务端返回304 Not Modified If-None-Match:
W/“4fd3169315a2307bef83eb3fce4d1382” Connection 用来指定当前的请求/回复中的,是否使用缓存机制。 Connection: keep-alive
Content-Type 请求体的MIME类型 (用于POST和PUT请求中) Content-Type:application/json;charset=UTF-8
Date 发送该消息的日期和时间(以RFC 7231中定义的”HTTP日期”格式来发送) Date: Dec, 26 Dec 2015 17:30:00 GMT
Referer 表示浏览器所访问的前一个页面,可以认为是之前访问页面的链接将浏览器带到了当前页面。Referer其实是Referrer这个单词,但RFC制作标准时给拼错了,后来也就将错就错使用Referer了。 Referer: http://itbilu.com/nodejs
User-Agent 浏览器的身份标识字符串 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Cookie 由之前服务器通过Set-Cookie(见下文)设置的一个HTTP协议Cookie Cookie: $Version=1; Skin=new;
响应头字段 说明 示例
Access-Control-Allow-Origin 指定哪些网站可以跨域源资源共享 Access-Control-Allow-Origin: *
Age 响应对象在代理缓存中存在的时间,以秒为单位 Age: 12
Cache-Control 通知从服务器到客户端内的所有缓存机制,表示它们是否可以缓存这个对象及缓存有效时间。其单位为秒 Cache-Control: max-age=3600
Date 此条消息被发送时的日期和时间(以RFC 7231中定义的”HTTP日期”格式来表示) Date: Tue, 15 Nov 1994 08:12:31 GMT
ETag 对于某个资源的某个特定版本的一个标识符,通常是一个 消息散列 ETag: “737060cd8c284d8af7ad3082f209582d”
Expires 指定一个日期/时间,超过该时间则认为此回应已经过期 Expires: Thu, 01 Dec 1994 16:00:00 GMT
Last-Modified 所请求的对象的最后修改日期(按照 RFC 7231 中定义的“超文本传输协议日期”格式来表示) Last-Modified: Dec, 26 Dec 2015 17:30:00 GMT
Refresh 用于重定向,或者当一个新的资源被创建时。默认会在5秒后刷新重定向 Refresh: 5; url=http://itbilu.com
Server 服务器的名称 Server: nginx/1.6.3
Set-Cookie 设置HTTP cookie Set-Cookie: UserID=itbilu; Max-Age=3600; Version=1
Content-Encoding 服务端能够发送压缩编码类型 Content-Encoding: gzip
Content-Type 服务端发送的类型及采用的编码方式 text/html; charset=GB2312
------ 本文结束------
0%