浏览器缓存机制:浏览器缓存机制,其实主要就是http协议定义的缓存机制(如:Expires;Cache-control等)。也有非http协议定义的缓存机制,如html meta标签:<meta http-equiv="Pragma" content="no-cache">,作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。
注意:浏览器会在第一次请求完服务器后得到响应,我们可以在服务器中设置这些响应,从而达到在以后的请求中尽量减少甚至不从服务器端获取资源的目的。浏览器是依靠请求和响应中的头信息来控制缓存的。
读取缓存的流程:有两步,首先根据约定时间,约定时间过来再来判断下面两种方式。
image.png
Expires与Cache-Control:就是服务器端用来约定和客户端的有效时间。
image.png
Expires规定了缓存失效(Date为当前时间),而Cache-Control的max-age规定了缓存有效时间(2552s)。Expires是http1.0的东西,而Cache-Control是http1.1的,规定如果max-age和Expires同时存在,前者优先级高于后者。Cache-Control的参数可以设置如下值:
image.png
为了决定浏览器是读取本地缓存还是去服务器拉取数据,就需要判断服务器上的文件是否有更新,有以下两种方式:
一:在上一次服务器端告诉客户端约定的有效期的同时,告诉客户端该文件最后修改的时间,当再次尝试从服务器端下载该文件的时候,check下该文件有没有更新(对比最后修改时间),如果没有,则读取缓存。(last-Modified / if-Modified-Since 要配合Cache-Control使用)
last-Modified是响应头返回来的信息,是服务器告诉浏览器被请求文件最后一次修改的时间;当浏览器再次请求该文件的时候,请求头中包含了if-Modified-Since项,将这个日期和服务器端该文件最后一次修改日期对比,如果相同,则相应http304,从缓存读数据;如果不相同,文件更新了,则相应http200,返回数据,同时通过响应头更新last-Modified的值。
二:在上一次服务器端告诉客户端约定有效期的同时,同时告诉客户端该文件的版本号,当服务器端文件更新的时候,改变版本号,再次发送请求的时候check一下版本号是否一致就行了,如一致,则直接读取缓存。(ETag / if-None-Match 要配合Cache-Control使用 )
ETag并不是文件的版本号,而是一串可以代表该文件唯一的字符串(Apache中,ETag的值,默认是对文件的索引节点,大小和最后修改时间进行Hash后得到的。),当客户端发现和服务器端约定的直接读取缓存的时间过了,就在请求头中发送if-None-Match选项,值为上次请求后响应头的ETag值,该值在服务器端和服务端代表改文件唯一的字符串对比(如果服务器端该文件改变了,该值就会变),如果相同,则相应http304,客户端直接读取缓存,否则,http200,下载正确的数据,更新ETag值。
当发送的请求头中同时存在if-None-Match和if-Modified-Since时,前者会优先于后者,忽略后者。http1.1中ETag的出现主要是为了解决几个Last-Modified比较难解决的问题:
1.last-Modified标注的最后修改只能精确到秒级,如果某些文件在一秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间。
2.如果某些文件会被定期生成,但有时内容并没有任何变化(仅仅改变了时间),但last-Modified却改变了,导致文件没法使用缓存。
3.有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情况。
无法被浏览器缓存的请求:
1.http信息头中包含Cache-Control:no-cache,pragma:no-cache(http1.0),或cache-Control:max-age=0等告诉浏览器不用缓存的请求。
2.需要根据cookie,认证信息等决定输入内容的动态请求是不能被缓存的
3.经过https安全加密的请求
4.Post请求无法被缓存。
5.http响应头中不包含last-Modified / Etag,也不包含Cache-Control / Expires的请求无法被缓存。
用户行为与缓存:
image.png
当用户在按F5进行刷新的时候,会忽略Expries/Cache-Control的设置,会再次发送请求去服务器请求,而Last-Modified/Etag还是有效的,服务器会根据情况判断返回304还是200;而当用户使用ctrl+F5进行强制刷新的时候,只是所有的缓存机制都将失效,重新从服务器去拉取资源。
网友评论