对于一些具有重复性的 HTTP 请求,比如每次请求得到的数据都一样的,我们可以把这对「请求-响应」的数据都缓存在本地,那么下次就直接读取本地的数据,不必在通过网络获取服务器的响应了,这样的话 HTTP/1.1 的性能肯定肉眼可见的提升。
所以,避免发送 HTTP 请求的方法就是通过缓存技术,HTTP 设计者早在之前就考虑到了这点,因此 HTTP 协议的头部有不少是针对缓存的字段。
HTTP 缓存有两种实现方式,分别是强缓存和协商缓存。
浏览器会将需要缓存的资源以「请求 : 响应」这样的KV对格式缓存在本地。当浏览器尝试发起请求访问资源之前,会先根据URL和请求头在本地尝试命中缓存。
协商缓存 更加常用,而使用协商缓存时,If-None-Match / Etag 这对请求头 / 响应头更为常用。
| 缓存类型 | 获取资源形式 | 状态码 | 是否发送请求到服务器 |
|---|---|---|---|
| 强缓存 | 从缓存取 | 200(from disk cache) | 否,直接从缓存取 |
| 协商缓存 | 从缓存取 | 304(not modified) | 是,通过服务器来告知缓存是否可用 |
若缓存已过期,浏览器重新发起请求,强制服务器将最新的资源放入响应body并返回。
若缓存已过期,浏览器重新发起请求,与服务器协商是否应继续使用本地缓存。
强缓存使用 Cache-Control 作为响应头用以控制资源的缓存方式,当其值以如下方式设置时:
Cache-Control: max-age=3600
表示该资源将在3600s后被浏览器判定为过期。
协商缓存在使用 Cache-Control 的基础上,还通过其他的字段来协同控制(Etag更为常用):
[If-None-Match / Etag] 当浏览器从服务器获取资源时,响应头中会携带 Etag 字段,该字段的值(记为 x )被用以唯一标识某个资源。当该资源被判定过期,浏览器将以如下方式设置请求头,发起请求以询问资源是否未被修改(是否仍然可用):
If-None-Match: x // x 为该资源的Etag值
[If-Modified-Since / Last-Modified] 与上述类似,响应头中有 Last-Modified 字段,值为该资源最近修改的时间(记为 t ),当资源被判定过期,以如下请求头发起请求询问资源是否未被修改:
If-Modified-Since: t // t 为该资源最近修改的时间
