http 缓存 不是在http服务上进行缓存,而是将资源缓存放在 浏览器服务端,利用 http 报头的一系列字段通讯,浏览器或者服务端去判断 资源的缓存状态,时间,是否是最新资源等。

header解释

Expires

日期/时间之后,响应被认为是过期的 http1.1的属性

  1. response -> Expires: Wed, 21 Oct 2015 07:28:00 GMT

Age

一般当服务器用自己的缓存实体去响应请求的时候,可以用Age 去表示实体从产生到现在的时间。

response -> Age: 24    单位:秒

Cache-Control

用于声明服务端的缓存控制指令

request 控制指令

no-cache

no-cache这并不意味着“不缓存”。no-cache允许缓存存储响应,但要求它们在重用之前重新验证它。如果您想要的“不缓存”的感觉实际上是“不存储”,那么no-store就是要使用的指令。

request -> Cache-Control: no-cache

max-age

Cache-Control: max-age=604800
只接受 Age 值 小于max-age 的内容,即没有过期的请求对象。

max-stale

可以接受过去的对象,但是过期时间必须小于 max-stale

min-fresh

接受生命期大于其当前 Age 跟 min-fresh 值之和的缓存

response 控制指令

pubilc

可以用Cache中内容回应任何用户

private

只能用缓存内容回应先前请求该内容的具体用户

no-cache

可以设置那些内容不用缓存

max-age

设置响应中包含对象的过期时间

Etag

一个资源的(url)标记,服务端返回会返回这个资源的Etag,如果服务端修改了资源,在下次返回资源的时候会重新生成一个新的Etag,客户端在请求的时候会带上这个Etag(放在 If-None-Match 上) 服务端会通过Etag对资源进行对比。

ETag: W/"<etag_value>"
ETag: "<etag_value>"
etag_value 是一个随机串或者时间戳

If-None-Match

如果上次文件的 response-header 中含有Etag,则会用 if-none-match : 上次etag, 放在request中请求到服务器,服务判断后返回200或者304

If-None-Match: "<etag_value>"
If-None-Match: "<etag_value>", "<etag_value>", …
If-None-Match: *

If-Modified-Since

如果上次文件返回中包含 Last-Modified ,则会带上 If-Modified-Since:上次 Last-Modified, 放在request中请求到服务器,服务判断后返回200或者304

If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT

Last-Modified

服务器设置的文件最后修改时间,比如文件的最后修改时间或者最后创建时间

Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT

流程解释

http 缓存 - 图1

  1. 浏览器会先判断 Cache-Control 来判断内容是否过期,如果没有过期,则直接读取浏览器缓存,不发送http请求 (这里判断 Expires 也可以,但是 Expires 是再http1.1之前比较通用,1.1之后推荐使用 Cache-Control设置相对时间,而不是通过 Expires 设置的绝对时间,如果都设置了,优先Cache-Control 生效 )
  2. 浏览器判断请求的url 在上次请求是否有返回的Etag,如果有,则将这个Etag 的值放在请求头的 If-None-Match 中,请求到服务器,让服务器判断资源是否是最新的,如果服务端Etag未被修改,则返回给浏览器304,如果修改则取最新的资源 并返回200
  3. 然后浏览器判断请求的url 在上次请求是否有返回的 Last-Modified 信息,有则被 If-Modified-Since 带上请求到服务端,服务端判断 从 Last-Modified 的时间开始 是否有新的更新,返回304 或 200
  4. 如果没有Etag 也没有 Last-Modified 则直接向服务器发送请求。

强缓存和协商缓存

强缓存

Expires + Chahe-Control
浏览器直接通过上次访问该url 留下的 过期时间判断 资源是否过期,不向服务器发请求

协商缓存

( Etag + If-None-Match )/ (Last-Modified + If-Modified-Since)
通过上次请求响应头中的Etag 或者 Last-Modified 在本次请求头中 通过 If-None-Match 和 If-Modified-Since 发送给服务端,让服务端去判断资源是否有更新,返回给浏览器 304 或者200