HTTP缓存
重用已获取的资源,提高浏览器性能。
(私有)浏览器缓存
用于单独用户的,在浏览器里缓存浏览过的文档,提供缓存内容的离线浏览,避免再次向服务器发起多余的请求。
(共享)代理缓存
共享缓存可以被多个用户使用。使热门的资源被重复使用,减少网络拥堵。
缓存操作的目标
缓存的关键:request method 和目标URl。
一般只有get请求才会被缓存。
缓存控制
HTTP/1.1定义的Cache-Control头用来区分对缓存机制的支持情况。
禁止缓存
缓存中不能存储任何关于客户端请求和服务端相应的内容。每次由客户端发起的请求都会下载完整的响应内容。
Cache-Control: no-store
强制确认缓存
每次由请求发出时,缓存会将此请求发送到服务器,服务器会验证请求中描述的缓存是否过期,若未过期(返回304),则缓存才使用本地缓存副本。
Cache-Control: no-cache
私有缓存
表示该响应是专用于某单个用户的,中间人不能缓存此响应,该响应只能应用于浏览器私有缓存中。
Cache-Control: private
公共缓存
该响应可以被任何中间人缓存。(默认是private)
Cache-Control: public
缓存过期机制
max-age=表示资源能被缓存(保持新鲜)的最大时间,max-age是距离请求发起的时间的秒数。
Cache-Control: max-age=31536000
缓存验证确认
当缓存要使用一个陈旧的资源时,必须先验证他的状态,已过期的缓存将不被使用。
Cache-Control: must-revalidate
Pragma头
是HTTP/1.0标准中定义的一个header属性,效果和强制确认验证相同。通常用来向后兼容基于HTTP/1.0的客户端。
新鲜度
缓存驱逐:因为缓存只有有限的空间用于存储资源副本,所以缓存会定期的将一些副本删除。
服务端和客户端为每一个资源约定一个过期时间,在该过期时间之前,该副本就是新鲜的,过了时间之后,该副本变为陈旧的。
驱逐算法:用于将陈旧的副本替换为新鲜的。
Tips:陈旧的副本不会被直接清除或忽略,当客户端发起一个请求时,缓存检索到已有一个对应的陈旧资源(缓存副本),则缓存会先将此请求附加一个If-None-Match头,然后发给目标服务器,以此来检查该资源副本是否是依然还是算新鲜的,若服务器返回了 304 (Not Modified)(该响应不会有带有实体信息),则表示此资源副本是新鲜的,这样一来,可以节省一些带宽。若服务器通过 If-None-Match 或 If-Modified-Since判断后发现已过期,那么会带有该资源的实体内容返回。
计算缓存寿命:
- 有Cache-Control:max-age=n的头,相应的缓存寿命就是n。
- 没有以上属性,查看Expires属性,通过比较Expires的值和头里面Date属性的值来判断缓存是否还有效。
- 以上两个属性都没有,查找Last-Modified信息,缓存寿命=(Date - Last-Modified)/10
//缓存失效时间计算公式
expirationTime = responseTime + freshnessLifetime - currentAge
加速资源
采用revving技术,给不频繁更新的文件使用特定的命名方式:在url后面加上版本号(这个版本号可以是hash,或者时间戳等防止出现缓存碰撞的标记)。加上版本号后的资源被视作一个完全独立的新资源,会拥有很长的缓存过期时长。
缓存验证
当用户点击刷新按钮时会进行缓存验证。如果缓存的响应头里含有“Cache-control:must-revalidate”的定义,会在浏览过程中出发缓存机制。
ETags
缓存的强校验器,是一个对用户代理(User Agent)不透明的值。浏览器的HTTP客户代理不知道ETags代表什么,不能预测值,只能在后续的请求头上带上If-None-Match来验证缓存。
Last-Modified
缓存的弱校验器,只能精确到一秒,客户端可以在后续的请求中带上If-Modified-Since来验证缓存。
浏览器返回值
- 200 表示ok,返回正常的结果
- 304表示Not Modified表示浏览器可以使用本地缓存的文件。
带Vary头的响应
Vary Http响应头决定了对于后续的请求头,如何判断是请求一个新的资源还是使用缓存的文件。
只有当前的请求和(缓存)原始的请求头和缓存的请求头里的Vary匹配,才能使用缓存的相应。
使用Vary:User-Agent 来区分移动端和桌面端的展示内容。因为移动端和桌面端的请求头中的User-Agent不同。