浏览器缓存机制学习总结
浏览器缓存机制学习总结
最近在做一个考试系统时,由于经常加载试卷或图片等等静态资源,抽空学习了一下缓存机制,在此记录
为什么要使用缓存
1、通过HTTP协议,在客户端和浏览器建立连接时需要消耗时间,而大的响应需要在客户端和服务器之间进行多次往返通信才能获得完整的响应,这拖延了浏览器可以使用和处理内容的时间。这就增加了访问服务器的数据和资源的成本,因此利用浏览器的缓存机制重用以前获取的数据就变成了性能优化时需要考虑的事情。
2、流量啊,现在云服务器流量都是收费的(- -玩笑)
浏览器缓存机制简介
一般使用中,缓存策略都是通过http 请求或响应里的header字段定义的,且许多是搭配使用的
各个字段定义详见 http 缓存 MDN
常用的字段个人看来主要分为两个部分
- 缓存策略字段
- 缓存校验字段
接下来依次介绍
缓存策略字段
Pragma(http1.0),cache-control(http1.1)
Pragma
Pragma:no-cache可以禁用浏览器缓存,使得浏览器每次都会发起新请求去获取资源
Pragma的优先级比expires高,如果给Pragma:no-cache且给expires一个未过期的事件,浏览器仍会发起新请求
expires时服务端的时间,与客户端时间可能不一致哦
cache-control(重点)
http1.1新增加的cache-control字段来弥补Pragma的不足,来对缓存策略提供更细粒度的控制,可以定义的值如下
request header 请求头header可以定义的值:
response header 相应header可以定义的值:
对几个字段加以解释
- cache-control:no-cache ,强制浏览器不直接使用缓存,每次需要向服务器发起请求校验缓存有效性
- cache-control:max-age=1000 ,1000秒内,该资源有效,浏览器无需再次请求获取资源(response 200 from cache)
- cache-control:public ,可以被任何中间人(比如中间代理、CDN等)缓存。
- cache-control:private,该响应是专用于某单个用户的,中间人不能缓存此响应
cache-control优先级高于expirse
对缓存策略进行简单总结就是:
不会发起请求的场景:
- cache-control:max-age在有效期内
- 当前客户端时间未超过expirse
需要发起请求验证缓存是否有效的场景(需要配合if-modified-since || if-none-match),返回304可以在缓存取值:
- cache-control:no-cache
- cache-control:max-age超出有效期
- 当前客户端时间超过expirse
必须发起请求获取新资源的场景:
- cache-control:no-store
缓存校验字段
last-modifed,e-tag
last-modified
该字段定义了资源上次的修改时间
场景:(cache-control:no-cache)
当客户端请求相应资源时,服务端会返回last-modified字段
客户端再次请求相应资源时会带上if-modified-since:(last-modified)value,
如果资源未改动(资源的last-modified <=if-modified-since)则返回304,
如资源已更新,返回新资源(200),同时更新last-modified的值
如果是cache-control:max-age=?,请求之前还会判断有效期(可能就无需请求了,直接从浏览器缓存获取)
e-tag
e-tag是服务端对某个资源计算出来的唯一指纹值,如果资源有改动,计算出来的指纹值会变化。
客户端请求时会带上之前服务端返回的 if-none-match:e-tag,服务端以指纹值是否相等为依据判断客户端的缓存是否有效。
如有效,返回304,如失效,返回200和新资源
e-tag的出现是弥补last-modified的不足
- last-modifie只能精确到秒,如一秒内多次更新,则不能获取最新资源
- 如果某资源是定期更新的但内容却可能未改变,
则last-modified每次都会更新而导致重复返回资源,
而e-tag值不会变因为内容不变,所以e-tag在这种场景下高效利用了缓存。
注意
如果服务端相应同时具有last-modified和e-tag,那么下次请求时会带上两者
- if-none-match: e-tag;
- if-modified-since: (last-modified)value
且这两者同时满足才会返回304,否则返回200。
实例
找个网站请求实例看一下字段我们都理解了没
如图这里的这个js资源是直接从http缓存直接加载的,肯定是上次请求的时间与现在相比没超过max-age。
写在最后
现在看这张图应该有点清晰了,这篇作为个人学习总结,许多细节不够详尽,实例操作不够,推荐各位去更加详尽参考资料中细细品读。