什么是浏览器缓存机制

浏览器缓存机制主要就是HTTP协议定义的缓存机制,比如ExpiresCache-control等。当然也有非HTTP协议的缓存机制,比如HTML Meta标签,即在HTML页面的<head>标签里面加入<meta>标签,像这样儿:

1
<meta html-equive="Pragma" content="no-cache">

这个标签告诉浏览器这个页面不被缓存,因此每次都需要去服务端拉取。但这种方式只有部分浏览器支持,而且所有缓存代理服务器都不支持,因为代理不解析html内容本身。

接下来,我们来看看HTTP协议的缓存机制。

Expires

Expires是服务相应消息头字段,在相应http请求时告诉浏览器在过期时间前,浏览器可以直接从浏览器缓存取数据,不用再次请求。例如服务器返回的头部:
Alt text

Data代表消息发送时间,时间格式是rfc822。此图显示缓存时间是5天。

ExpiresHTTP1.0的东东,现在浏览器默认使用的是HTTP1.1,因此它的作用可以忽略。

Cache-control

Cache-control和Expires的作用一样,都是说明当前资源的有效期,告诉浏览器是从缓存中读取缓存数据,还是向服务器发送请求拉取数据。但是Cache-control的选择更多,设置更详细,若同时设置,Cache-control的优先级是高于Expires的。
我们来看看HTTP协议头Cache-control里面都有什么:

  • public:标明响应可以被任何缓存区缓存
  • private:标明对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当前用户的部分响应消息,此响应消息对于其他用户的请求无效
  • no-cache:标明请求或响应消息不能缓存
  • no-store:用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存
  • no-transform:
  • must-revalidate:
  • proxy-recalidate:
  • max-age:标明客户机可以接收生存期不大于指定时间(以秒为单位)的响应
  • min-fresh:标明客户机可以接收响应时间小于当前时间加上指定时间的响应
  • max-stale:标明客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息

如下图:
Alt text

Last-Modified/If-Modified-Since

Last-Modified/If-Modified-Since要配合Cache-Control使用。

  • Last-Modified:标示这个响应资源的最后修改时间。web服务器在响应请求时,告诉浏览器资源的最后修改时间
  • If-Modified-Since:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Last-Modified声明,则再次向web服务器请求时带上头 If-Modified-Since,表示请求时间。web服务器收到请求后发现有头If-Modified-Since则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源又被改动过,则响应整片资源内容(写在响应消息包体内),HTTP 200;若最后修改时间较旧,说明资源无新修改,则响应HTTP 304 (无需包体,节省浏览),告知浏览器继续使用所保存的cache

Etag/If-None-Match

Etag/If-None-Match也要配合Cache-Control使用。

  • Etag:web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器觉得)。Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的
  • If-None-Match:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Etage声明,则再次向web服务器请求时带上头If-None-Match (Etag的值)。web服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200304

看到上面的解释,大家可能有个疑问,既然Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag(实体标识)呢?
HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:

  • Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
  • 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存
  • 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形

Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-ModifiedETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304

用户行为与缓存

用户行为 Expires/Cache-Control Last-Modified/Etag
地址栏回车 有效 有效
页面链接跳转 有效 有效
新开窗口 有效 有效
前进、后退 有效 有效
F5刷新 无效 有效
Ctrl+F5刷新 无效 无效

总结

浏览器第一次请求:
Alt text
浏览器再次请求:
Alt text

原文:浏览器缓存