持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
为什么要有缓存?
HTTP请求本身比较耗时,对于一些很少变化的资源,可以通过缓存减少网络请求,让页面加载更快。
通常会缓存静态资源(css,js,img),对于动态计算的页面则不会缓存。
强制缓存和协商缓存
缓存分为强制缓存和协商缓存,由服务器和浏览器共同控制。
- 强制缓存就是无条件缓存,优先级最高,浏览器在资源有效时间内不会请求服务器,直接使用。
- 协商缓存就是浏览器在使用前要访问服务器,问一问资源能不能用,服务器说能用才会用。
服务器缓存控制
强制缓存
强制缓存中,服务器只需要在响应头部中返回Cache-Control
字段即可控制。该字段指定了资源过期时间,资源只要不过期,浏览器就会一直使用。
Cache-Control
常用取值:
- max-age:最大过期时间,单位
秒
。如果max-age=0,则同no-cache - no-cache:无强制缓存,有协商缓存
- no-store:无强制缓存,也无协商缓存
- private:只允许最终用户缓存,比如浏览器
- public:允许代理服务器进行缓存
响应头部中Expires字段也用于控制缓存,优先级低于Catch-Control,属于比较老的标准。
max-age 是“生存时间”(又叫“新鲜度”“缓存寿命”,类似 TTL,Time-To-Live),时间的计算起点是响应报文的创建时刻(即 Date 字段,也就是离开服务器的时刻),而不是客户端收到报文的时刻,也就是说包含了在链路传输过程中所有节点所停留的时间。
协商缓存
协商缓存中,服务器需要在响应头部中返回Last-Modified
或ETag
记录资源状态,浏览器需要在请求头部中添加Last-Modified-Since
或If-None-Match
携带资源状态去服务器进行校验,服务器比对发现资源一样则返回304,浏览器使用缓存,不一样则返回200和最新的资源。
资源状态记录字段:
- Last-Modified:资源最后修改时间
- 浏览器通过If-Modified-Since携带Last-Modified的值
- ETag:资源唯一标识(一个字符串)
- 浏览器通过If-None-Match携带ETag的值
ETag优先级高于Last-Modified,如果两者共存优先使用ETag。
- Last-Modified只能精确到秒级,ETag更精准一些。
- 如果资源被重复生成,而内容不变,则ETag更精准。
浏览器缓存控制
- 前进后退:强制缓存和协商缓存均遵循服务器缓存策略
- 如果有强制缓存,则不产生请求,直接返回(disk cache)
- 如果有协商缓存,则携带
If-Modified-Since或If-None-Match
- ajax访问:强制缓存和协商缓存均遵循服务器缓存策略
- 如果有强制缓存,则不产生请求,直接返回(disk cache)
- 如果有协商缓存,则携带
If-Modified-Since或If-None-Match
- 页面刷新:输入URL回车或者点击刷新按钮,强制缓存失效,协商缓存遵循服务器缓存策略
- 浏览器在请求头部中携带
Cache-Control:max-age=0
- 如果有协商缓存,则携带
If-Modified-Since或If-None-Match
- 浏览器在请求头部中携带
- 强制刷新:shift+cmd+R,强制缓存和协商缓存均失效
- 浏览器在请求头部中携带
Cache-Control:no-cache
- 浏览器不会携带
If-Modified-Since或If-None-Match
- 浏览器在请求头部中携带
缓存访问整体流程
- 强制缓存是否有效?
- 强制缓存有效则访问缓存,流程结束
- 强制缓存失效则看是否有协商缓存?
- 不存在协商缓存,访问服务器获取新数据,流程结束
- 存在协商缓存,携带资源标识访问服务器
- 服务器判定资源一致,返回304,使用缓存,流程结束
- 服务器判定资源不一致,返回200和新数据,流程结束
如果强制缓存和协商缓存均失效,浏览器将删除该缓存