浏览器端的缓存规则">浏览器端的缓存规则
对于浏览器端的缓存来说,这些规则是在HTTP协议头和HTML页面的Meta标签中定义的。他们分别从新鲜度和校验值两个维度来规定浏览器是否可以直接使用缓存中的副本,还是需要去源服务器获取更新的版本。
新鲜度(过期机制):也就是缓存副本有效期。一个缓存副本必须满足以下条件,浏览器会认为它是有效的,足够新的:
满足以上两个情况的一种,浏览器会直接从缓存中获取副本并渲染。
校验值(验证机制):服务器返回资源的时候有时在控制头信息带上这个资源的实体标签Etag(Entity Tag),它可以用来作为浏览器再次请求过程的校验标识。如过发现校验标识不匹配,说明资源已经被修改或过期,浏览器需求重新获取资源内容。
浏览器缓存的控制
使用HTML Meta 标签
Web开发者可以在HTML页面的
上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。使用上很简单,但只有部分浏览器可以支持,而且所有缓存代理服务器都不支持,因为代理不解析HTML内容本身。
使用缓存有关的HTTP消息报头
在HTTP请求和响应的消息报头中,常见的与缓存有关的消息报头有:
Expires与Cache-Control
首先说明一点:Cache-Control与Expires的作用一致,都是指明当前缓存文件的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过Cache-Control的选择更多,设置更细致,如果同时设置的话,其优先级高于Expires。
对于上图中的响应头来说:
Date是当前时间,Expires规定了缓存失效时间(日期),而Cache-Control的max-age规定了缓存有效时间(距离失效的秒数),理论上这两个值计算出的有效时间应该是相同的。Expires属于HTTP1.0,而Cache-Control属于HTTP1.1。
注意:**规定如果max-age和Expires同时存在,Cache-Control优先级高于Expires。**Cache-Control的参数可以设置很多值,譬如(参考浏览器缓存机制):
Cache-Control头
**值可以是:**public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age
各个消息中的指令含义是:
Last-Modified和ETag与Cache-Control和Expires
配置Last-Modified/ETag的情况下,浏览器再次访问统一URI(统一资源标识符)的资源,还是会发送请求到服务器询问文件是否已经修改,如果没有,服务器会只发送一个304回给浏览器,告诉浏览器直接从自己本地的缓存取数据;如果修改过,那就最新的文件发给浏览器;
Cache-Control/Expires则不同,如果检测到本地的缓存还是有效的时间范围内,浏览器直接使用本地副本,不会发送任何请求。两者一起使用时,Cache-Control/Expires的优先级要高于Last-Modified/ETag。即当本地副本根据Cache-Control/Expires发现还在有效期内时,则不会再次发送请求去服务器询问修改时间(Last-Modified)或实体标识(Etag)了。
注意:一般情况下,需要Cache-Control/Expires配合Last-Modified/ETag一起使用,因为即使服务器设置缓存时间, 当用户点击“刷新”按钮时,浏览器会忽略缓存继续向服务器发送请求,这时Last-Modified/ETag将能够很好利用304,从而减少响应开销(这里只是避免了服务器响应数据,也就是说如果响应304。服务不再返回数据,浏览器直接使用缓存文件,但是浏览器端依旧会发送请求)。
Last-Modified与If-Modified-Since
Last-Modified/If-Modified-Since就是上面说的当有效期过后,check服务端文件是否更新的第一种方式,要配合Cache-Control使用。比如响应头信息: ETag/If-None-Match是第二种check服务端文件是否更新的方式,也要配合Cache-Control使用。实际上ETag并不是文件的版本号,而是一串可以代表该文件唯一的字符串(Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。),当客户端发现和服务器约定的直接读取缓存的时间过了,就在请求中发送If-None-Match选项,值即为上次请求后响应头的ETag值,该值在服务端和服务端代表该文件唯一的字符串对比(如果服务端该文件改变了,该值就会变),如果相同,则响应HTTP304,客户端直接读取缓存,如果不相同,则响应HTTP200,下载正确的数据,更新ETag值。 Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。 无法被浏览器缓存的请求: HTTP信息头中包含Cache-Control:no-cache,pragma:no-cache,或Cache-Control:max-age=0等告诉浏览器不用缓存的请求 需要根据Cookie,认证信息等决定输入内容的动态请求是不能被缓存的 说明:之前也知道浏览器的缓存机制,但是总是迷迷糊糊的。今天特地查了很多资料,并和小伙伴们一起讨论了这个问题,算是就加深了理解吧。特此整理了一下,这里特别感谢参考博文的作者,学习还是要多思考,多查资料,多总结,继续加油!!
按下ctrl+r刷新,因为ctrl+r会默认跳过max-age和Expires的检验直接去向服务器发送请求,看下图:
请求头中包含了If-Modified-Since项,而它的值和上次请求响应头中的Last-Modified一致,我们发现这个日期是2013年,也就是说这个文件自从2013年的那个日期后就没有再被修改过了。
核心思想:<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPr2rSWYtTW9kaWZpZWQtU2luY2W1xMjVxtq6zbf+zvG2y7jDzsS8/rXE1+6689DeuMTI1cbattSxyKOsyOe5+8G9uPbI1cbaz+DNrKOs1PLP7NOmSFRUUDMwNKOstNO7urTmtsHK/b7do7vI57n7srvP4M2s1PKx7cq+zsS8/reiyfqx5LuvuPzQwqOsz+zTpkhUVFAyMDCjrLTTt/7O8cb3t7W72Nfu0MK1xM7EvP7K/b7do6zNrMqxuPzQws/s06bNt2xhc3QtTW9kaWZpZWS1xNa1o6jS1LG4z8K0zrbUscijqaGjPC9wPg0KPGgzIGlkPQ=="etag与if-none-match">ETag与If-None-Match
结合上图来说:当浏览器缓存过期之后,客户端就会重新向服务器发送请求,请求头中带If-None-Match项,该字符串值会在服务端进行匹配,很显然,并没有什么变化(对比响应头的ETag值),于是响应HTTP304,直接读取缓存。
细心的你或许发现了:该请求中也有If-Modified-Since项,如果两者同时存在,If-None-Match优先,忽略If-Modified-Since。或许你会问为什么它优先?两者功能相似甚至相同,为什么要同时存在?HTTP1.1中ETag的出现主要是为了解决几个Last-Modified比较难解决的问题:用户操作行为与缓存
通过上表我们可以看到,当用户在按F5进行刷新的时候,会忽略Expires/Cache-Control的设置,会再次向服务器发送请求,而Last-Modified/Etag还是有效的,服务器会根据情况判断返回304还是200;而当用户使用Ctrl+F5进行强制刷新的时候,所有的缓存机制都将失效,重新从服务器获取资源。哪些请求不能被缓存?
小结
上图对于浏览器缓存机制描述的很详细,这里我对其做了一下语言描述。
个人理解,如有错误,请指正
当客户端向服务器发送一个请求时,首先检查是否存在缓存,有缓存文件则判断缓存文件是否过期,如果缓存文件没有过期,则直接从缓存中读取文件。
如果缓存文件过期,则查看响应头中是否存在Etag,如果不存在,则继续查看响应头中是否存在Last-Modified,如果也不存在,则直接向服务器发送新的请求,等待请求响应,缓存协商,呈现页面。
如果缓存文件过期,响应头中存在ETag,向服务器发送带If-None-Match的请求,值即为上次请求后响应头的ETag值,该值在服务端和服务端代表该文件唯一的字符串对比(如果服务器端该文件更新了,该值就会变),如果相同,则响应HTTP304,客户端直接读取缓存文件,如果不相同,则响应HTTP200,服务器返回最新的文件,同时更新ETag值。
如果缓存文件过期,响应头中不存在Etag,但是存在Last-Modified,则向服务器发送带If-Modified-Since的请求,将If-Modified-Since的日期和服务端该文件的最后修改日期对比,如果两个日期相同,则响应HTTP304,客户端直接读取缓存文件;如果不相同则表示文件发生变化更新,响应HTTP200,从服务器返回最新的文件数据,同时更新响应头last-Modified的值(以备下次对比)。