问题描述
最近对文件上传功能进行了优化改版,上线之后有同事反馈出来,自从上线之后所上传的图片,均没有设置浏览器端缓存,导致客户端每次都要去请求服务器上的图片资源,会导致页面加载速度变慢,用户体验不好诸类问题。之前从未接触过此类问题赶忙查阅了浏览器缓存的相关知识,并对问题进行了修复,现将一些所学进行整理归纳。
HTTP的缓存机制
在Chrom浏览器中打开一张图片,比如华为新款P30手机,选择一张图片(https://res9.vmallres.com/shopdc/pic/e769ea22-d741-45fd-94e8-1b39deb19719.jpg),查看它的网络请求信息。
第一次请求
第二次请求
强缓存
可以理解为无须验证的缓存策略。对强缓存来说,响应头中有两个字段 Expires/Cache-Control 来表明规则。
Expires
Expires 指缓存过期的时间,超过了这个时间点就代表资源过期。有一个问题是由于使用具体时间,如果时间表示出错或者没有转换到正确的时区都可能造成缓存生命周期出错。
Cache-Control
Cache-Control 可以由多个字段组合而成,主要有以下几个取值:
Cache-Control: max-age =? : 指定一个时间长度,在这个时间段内缓存是有效的,单位是s。例如设置 Cache-Control:max-age=31536000,也就是说缓存有效期为(31536000 / 24 / 60 * 60)天。
Cache-Control: no-cache强制所有缓存了该响应的用户,在使用已缓存的数据前,发送带验证器的请求到服务器。不是字面意思上的不缓存。
Cache-Control: no-store
才是真正的不缓存数据到本地
Cache-Control: public
可以被所有用户缓存(多用户共享),包括终端和CDN等中间代理服务器
Cache-Control: private
只能被终端浏览器缓存(而且是私有缓存),不允许中继缓存服务器进行缓存
协商缓存
缓存的资源到期了,并不意味着资源内容发生了改变,如果和服务器上的资源没有差异,实际上没有必要再次请求。客户端和服务器端通过某种验证机制验证当前请求资源是否可以使用缓存。
浏览器第一次请求数据之后会将数据和响应头部的缓存标识存储起来。再次请求时会带上存储的头部字段,服务器端验证是否可用。如果返回 304 Not Modified,代表资源没有发生改变可以使用缓存的数据,获取新的过期时间。反之返回 200 就相当于重新请求了一遍资源并替换旧资源。
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。
缓存流程
用户行为与缓存的使用方式
参考资料:
https://zhuanlan.zhihu.com/p/29750583