Fork me on GitHub
代码改变世界

浏览器缓存机制

2015-09-05 18:34  autrol  阅读(237)  评论(0编辑  收藏  举报

浏览器缓存机制

浏览器缓存机制,其实主要就是HTTP协议定义的缓存机制(如: Expires; Cache-control等)。但是也有非HTTP协议定义的缓存机制,如使用HTML Meta 标签,Web开发者可以在HTML页面的<head>节点中加入<meta>标签,代码如下:

<meta http-equiv="Pragma" content="no-cache" />

 

Expires

Expires是Web服务器响应消息头字段,在响应http请求时告知浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求

Date表示发送请求的时间,Expires表示文件过期的时间,从上图可以看出,Web服务器告诉浏览器在2015-10-5 07:30:47这个时间点之前,可以使用缓存文件,发送请求的时间是2015-08-30 07:30:47

不过Expires是HTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。

 

Cache-control

Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过Cache-Control的选择更多,设置更细致,如果同时设置的话,其优先级高于Expires

Cache-Control:可以取值public/private/no-cache/no-store/max-age/min-fresh/max-stale

  • public:指示响应可被任何缓存区缓存
  • private:指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效
  • no-cache:指示请求或响应消息不能缓存,则cache 不能使用响应来满足随后请求,以秒为单位,它必须成功与源头服务器校验之后才可以,也就是我们后面说到的304状态码
  • no-store:用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。这个指令适用于整个消息,可以应用在请求头或者响应头中。如果在请求中发送,则一个cache不能存储这个请求或者随后的响应。如果发送在响应中,一个cache不可以存储响应的任何部分以及相关的部分(这才是真正的不缓存)
  • max-age:指示客户端愿意接受存活时间不大于这里指定的描述的响应。除非max-stale也存在,否则客户端将不愿意接受不新鲜的响应
  • min-fresh:客户端要一个新鲜时间至少是这么多的响应
  • max-stale:指示客户端愿意接受一个超过了过期时间的响应。如果max-stale后面带有值,则它不能接受过期时间超过这个值的响应,如果没有值,则可以接受任何时候的过期响应

还是上面那个请求,web服务器返回的Cache-Control头的值为max-age=3110400

 

 

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

你可能会觉得使用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刷新 无效 无效

 

总结

浏览器第一次请求:

浏览器再次请求时:

 

清理缓存

Ctrl+Shift+Delete浏览器清理缓存、通过浏览器清理缓存选项整体清理缓存、Ctrl+F5清理当前页缓存