缓存的规则
HTTP
的缓存属于客户端缓存,所以我们可以认为浏览器存在一个缓存数据库,用于储存一些不经常变化的静态文件(图片、css、js
等)。可以将缓存分为强制缓存和协商缓存。
强制缓存
可以理解为无须验证的缓存策略。对强缓存来说,响应头中有两个字段 Expires/Cache-Control
来表明规则。
当缓存数据库中已有所请求的数据时。客户端直接从缓存数据库中获取数据。当缓存数据库中没有所请求的数据时,客户端的才会从服务端获取数据。
Expires
Expires
的值为服务端返回的到期时间,即下一次请求时,请求时间小于服务端返回的到期时间,直接使用缓存数据。 不过Expires
是HTTP 1.0
的东西,现在默认浏览器均默认使用HTTP 1.1
,所以它的作用基本忽略。 另一个问题是,到期时间是由服务端生成的,但是客户端时间可能跟服务端时间有误差,这就会导致缓存命中的误差。 所以HTTP 1.1
的版本,使用Cache-Control
替代。
Cache-Control
Cache-Control
有很多属性,不同的属性代表的意义也不同。
private
:客户端可以缓存public
:客户端和代理服务器都可以缓存max-age=t
:指定一个时间长度,在这个时间段内缓存是有效的,单位是s.no-cache
: 告诉浏览器、缓存服务器,不管本地副本是否过期,使用资源副本前,一定要到源服务器进行副本有效性校验。must-revalidate
:告诉浏览器、缓存服务器,本地副本过期前,可以使用本地副本;本地副本一旦过期,必须去源服务器进行有效性校验。no-store
:禁止缓存,每次请求都要向服务器重新获取数据。
协商缓存
又称对比缓存,客户端会先从缓存数据库中获取到一个缓存数据的标识,得到标识后请求服务端验证是否失效,如果没有失效服务端会返回304,此时客户端直接从缓存中获取所请求的数据,如果标识失效,服务端会返回更新后的数据。
Last-modified/If-Modified-since
Last-modified
: 服务器端资源的最后修改时间,响应头部会带上这个标识。第一次请求之后,浏览器记录这个时间,再次请求时,请求头部带上 If-Modified-Since
即为之前记录下的时间。服务器端收到带 If-Modified-Since
的请求后会去和资源的最后修改时间对比。若修改过就返回最新资源,状态码 200
,若没有修改过则返回 304
。
Etag/If-None-Match
由服务器端上生成的一段 hash
字符串,第一次请求时响应头带上 ETag: abcd
,之后的请求中带上 If-None-Match: abcd
,服务器检查 ETag
,返回 304
或 200
。
但是实际应用中由于Etag
的计算是使用算法来得出的,而算法会占用服务端计算的资源,所有服务端的资源都是宝贵的,所以就很少使用Etag
了。
关于 last-modified
和 Etag
区别,已经有很多人总结过了:
- 某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新。
Last-modified
只能精确到秒。- 一些资源的最后修改时间改变了,但是内容没改变,使用
Last-modified
看不出内容没有改变。 Etag
的精度比Last-modified
高,属于强验证,要求资源字节级别的一致,优先级高。如果服务器端有提供 ETag 的话,必须先对 ETag 进行 Conditional Request。