浏览器缓存 (Last-Modified & Etag, cache)

创建时间:
2014-07-25 21:28
最近更新:
2018-10-07 16:20

Resource

  1. HTTP 缓存工作流程详解
  2. HTTP 协议定义的缓存机制
  3. 浏览器 HTTP 协议缓存机制详解
  4. 浅谈浏览器 HTTP 的缓存机制
  5. 浅谈 Web 缓存
  6. HTTP 缓存
  7. Web 开发人员需知的 Web 缓存知识 - 张鑫旭 2013-06-16
  8. 作为前端应当了解的 Web 缓存知识
  9. 浏览器缓存知识小结及应用 Tony Praise
  10. 透过浏览器看 HTTP 缓存
  11. 浏览器缓存知识小结及应用
  1. JavaScript 清除浏览器缓存的几种方法
  2. 通过 png 图的 rgba 值缓存数据

网摘

浏览器在发出请求前,
如是 http1.0 则检查响应头中的 max-ageExpires
如是 http1.1 则检查响应头中的 Cache-Control:max-age=315360000
据此判断响应是否已过期。
如未过期,叫作 "命中强缓存",此时浏览器不发起请求,而是直接读取本地的缓存数据。
如已过期,浏览器会发起请求。
如果响应头中有 LastModified 或者 Etag,会将这两类信息放在请求头中发送至服务器,服务器收到后会与资源进行比对,如一致,叫作 "命中协商缓存",此时响应状态码 304 (Not Modified),浏览器收到 304 响应即读取本地的缓存数据。

强缓存与协商缓存的共同点: 如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源; 区别是 强缓存不发出请求,协商缓存会发送请求到服务器。如协商缓存也未命中则浏览器直接从服务器加载资源。

服务器可在响应中向浏览器传递各种与缓存相关的各种参数,例如 Etagno-cache 等。但是这些参数仅相当于 "建议",最终是否缓存由各个浏览器自身的实现来决定。

什么是 Last-Modified

浏览器第一次请求某个 URL,正常情况下服务器端的返回,状态是 200、内容是你请求的资源。同时有一个 Last-Modified 的属性,用于标记此文件在服务期端最后被修改的时间,其格式类似 Last-Modified: Fri, 12 May 2006 18:53:33 GMT

客户端第二次请求此 URL 时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头 If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT,询问该时间之后文件是否有被修改过。

如果服务器端的资源没有变化,则自动返回 HTTP 304 (Not Changed.) 状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。

什么是 Etag

"HTTP 协议规格说明" 定义 ETag 为 "被请求变量的实体值" (参见章节 14.19)。另一种说法是,ETag 是一个可以与 web 资源关联的记号 (token)。典型的 web 资源可以一个 web 页,但也可能是 JSON 或 XML 文档。服务器单独负责判断记号是什么及其含义,并在 HTTP 响应头中将其传送到客户端,以下是服务器端返回的格式:ETag: "50b1c1d4f775c61:df3"

客户端的查询更新格式是这样的:If-None-Match: W/"50b1c1d4f775c61:df3"

如果 ETag 没改变,则返回状态 304 然后不返回,这也和 Last-Modified 一样。Etag 主要用于断点续传。

Last-Modified 和 Etags 如何帮助提高性能

聪明的开发者会把 Last-Modified 和 ETags 请求的 http 报头一起使用,这样可利用客户端 (例如浏览器) 的缓存。因为服务器首先产生 Last-Modified / Etag 标记,服务器可在稍后使用它来判断页面是否已经被修改。本质上,客户端通过将该记号传回服务器要求服务器验证其 (客户端) 缓存。

过程如下:

  1. 客户端请求一个页面 A。
  2. 服务器返回页面 A,并在给 A 加上一个 Last-Modified / ETag。
  3. 客户端展现该页面,并将页面连同 Last-Modified / ETag 一起缓存。
  4. 客户再次请求页面 A,并将上次请求时服务器返回的 Last-Modified / ETag 一起传递给服务器。
  5. 服务器检查该 Last-Modified 或 ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应 304 和一个空的响应体。