页面的性能优化,设置缓存是个效果非常好的点,一定要学会。
HTTP请求(Request)报文,报文格式为:请求行 – HTTP头(通用信息头,请求头,实体头) – 请求报文主体(只有POST才有报文主体)
HTTP响应(Response)报文,报文格式为:状态行 – HTTP头(通用信息头,响应头,实体头) – 响应报文主体

上图我们可以看到
- 每一次发起http请求,都会在浏览器缓存里查找缓存的内容和标识
- 每一次的http的响应,都会将结果和标识存入浏览器缓存中
强制缓存
涉及到的字段是 Expires and Cache-Control,其中Cache-Control的优先级高过Expires
Expires: 从服务器响应缓存结果到缓存失效的时间,这是个绝对时间
Cache-Control:
public:所有内容都将被缓存(客户端和代理服务器都可缓存)
private:所有内容只有客户端可以缓存,Cache-Control的默认取值
no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效
- 特别要留心max-age这种情况,常常被问,这是个相对时间,时间为XXX秒
强制缓存有三种情况:
- http response 没有强制缓存内容和标识,这会按照没有缓存的请求,直接去请求服务器。
- http response 有强制缓存内容和标识,但是失效了,就会进入到协商缓存。
- http response 有强制缓存内容和标识,并且没有失效,直接缓存文件。
下面看一下协商缓存:
- 涉及到协商缓存的字段有:
Last-Modifined/If-Modified-Since
- Last-Modifined:是响应头内的信息,反映的是该文件最后在服务器修改的时间。
- If-Modified-Since:则是客户端再次发起请求,携带上次请求返回的Last-Modifined的值,通过这个字段告诉服务器上次请求修改的时间,如果If-Modified-Since大于文件在服务器最后修改的时间,那么就返回新的资源,状态码是200,相反是304.
Etag/If-None-Match
Etag在响应头内,是当前资源的惟一标识(由服务器下发)
If-None-Match是上一次请求返回的Etag值,然后发送到服务端,去和在服务器上的Etag值去比较,看是否有变化,一致返回304,返回缓存资源,不一致返回200,发送新的资源。
返回码总结
| 缓存 | 状态码 | 是否发送到服务器 |
|---|---|---|
| 强缓存 | 200 | 否,直接从浏览器缓存读取 |
| 协商缓存 | 304 | 是,通过服务器告诉浏览器缓存是否可用 |
流程总结

从上图我们看到,优先级如下:
强缓存->协商缓存(Etag->Last-modified)
Q:为什么有Last modified还要有Etag?
- 有些文件周期性改变,但是内容没有改变,这个时候不想浪费资源请求,就对比Etag和If-none-Match.
- 因为Last-modified-since是秒级别的,如果一秒修改了多次,Last-modified-since是发现不了缓存失效的,这个时候Etag就派上了用场。