当前位置: 首页 > Web前端 > HTML

浏览器缓存机制

时间:2023-03-28 11:51:14 HTML

概述浏览器缓存机制就是我们所说的HTTP缓存机制。该机制基于HTTP消息的缓存标识符。因此,在分析浏览器缓存机制之前,我们先用图文简单介绍一下HTTP报文。HTTP消息分为两种类型:HTTP请求(Request)消息。消息格式为:请求行-HTTP头(通用信息头、请求头、实体头)-请求消息体(只有POST有消息体),如下图,HTTP响应(Response)消息,消息格式为:StatusLine–HTTPHeader(GeneralInformationHeader,ResponseHeader,EntityHeader)–ResponseMessageBody,如下图所示:是Cache-Control、Connection、Date、Pragma、Transfer-Encoding、Upgrade和Via;实体头是指实体信息的实体头字段,分别为Allow、Content-Base、Content-Encoding、Content-Language、Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、Etag、Expires、Last-Modified、扩展头。这里只是为了方便理解,一般信息头、响应头/请求头、实体头都归类为HTTP头。以上概念我们这里不做解释,只是简单介绍一下。有兴趣的童鞋可以自行研究。缓存过程分析浏览器与服务器通信的方式为响应方式,即:浏览器发起HTTP请求——服务器响应请求。然后浏览器第一次向服务器发起请求并得到请求结果后,会根据响应报文中HTTP头的缓存标识决定是否缓存该结果,如果缓存则存储请求结果以及浏览器缓存中的缓存标识,很简单流程如下图所示:从上图我们可以知道,浏览器每次发起请求,都会先去查找请求的结果,然后浏览器缓存中的缓存标识符。以上两个结论是浏览器缓存机制的关键。它保证了每个请求的缓存存储和读取。只要了解浏览器缓存的使用规律,一切问题迎刃而解。是的,本文也将围绕这一点进行详细的分析。为了方便大家理解,这里我们根据是否需要向服务器重新发起HTTP请求,将缓存过程分为两部分,即强制缓存和协商缓存。强制缓存强制缓存是在浏览器缓存中查找请求结果,并根据结果的缓存规则决定是否使用缓存结果的过程。强制缓存主要有三种情况(暂不分析协商缓存过程),如下:No如果缓存结果和缓存ID存在,如果缓存失效,则直接向服务器发起请求(与第一次请求),如下图:如果缓存结果和缓存ID存在,但是结果已经过期,如果缓存失效,则使用协商缓存(暂不分析),缓存结果和缓存ID存在下图,且结果未过期,强制缓存生效,直接返回结果,如下图,那么强制缓存的缓存规则是什么?当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中,连同请求结果一起返回给浏览器。控制强制缓存的字段有Expires和Cache-Control,其中Cache-ControlPriority高于Expires。ExpiresExpires是HTTP/1.0控制网页缓存的一个字段。它的值是服务器返回请求的缓存结果时的过期时间。即再次发起请求时,如果客户端的时间小于Expires的值,则直接使用缓存的结果。Expires是HTTP/1.0的一个字段,但是现在浏览器默认使用HTTP/1.1,那么网页缓存是否仍然由HTTP/1.1中的Expires控制?到HTTP/1.1,Expire已经被Cache-Control取代。原因是Expires控制缓存的原理是比较客户端返回的时间和服务器返回的时间。如果由于某些原因导致客户端和服务器的时间不同(比如时区;如果客户端和服务器的时间不准确),那么强制缓存将直接失效。在这种情况下,强制缓存的存在是没有意义的,那么Cache-Control是如何控制的呢?Cache-Control在HTTP/1.1中,Cache-Control是最重要的规则,主要用来控制网页缓存,主要取值有:public:所有内容都会被缓存(客户端和代理服务器都可以缓存)private:全部内容只能由客户端缓存。Cache-Control的默认值为no-cache:客户端缓存内容,但是否使用缓存需要协商后验证。no-store:所有内容都不会被缓存,即不使用强制缓存,不使用协商缓存max-age=xxx(xxx为数字):缓存的内容会在xxx秒后过期接下来我们直接看例子,如下:从上面的例子,我们可以知道:HTTP响应报告文章中expires的时间值是一个绝对值。HTTP响应报文中的Cache-Control是max-age=600,是一个相对值。因为Cache-Control的优先级高于expires,所以直接根据Cache-Control的值进行缓存。这意味着如果在600秒内再次发起请求,将直接使用缓存的结果强制缓存生效。注意:当无法判断客户端的时间是否与服务器的时间同步时,Cache-Control是比expires更好的选择,所以当两者都存在时,只有Cache-Control生效。了解了强制缓存的过程后,我们再广泛地思考一下:浏览器的缓存存储在哪里,如何判断强制缓存在浏览器中是否有效?这里我们以博客请求为例。状态码为灰色的请求表示使用了强制缓存,请求对应的Size值表示缓存的存储位置,分别来自内存缓存和磁盘缓存。那么frommemorycache和fromdiskcache分别代表什么?什么时候使用fromdiskcache,什么时候使用frommemorycache?frommemorycache是??指使用内存中的cache,fromdiskcache是??指使用硬盘中的cache。浏览器读取缓存的顺序是内存->磁盘。虽然直接把结论说了出来,但是相信很多人都看不懂,下面就详细分析一下缓存读取问题,并以我的博客为例进行分析:访问https://heyingye.github.io/–>200–>关闭博客的标签–>重新打开https://heyingye.github.io/–>200(fromdiskcache)–>refresh–>200(frommemorycache)过程如下:访问https://heyingye.github.io/关闭博客的标签,重新打开https://heyingye.github.io/刷新看到这里可能有朋友问,当最后一步刷新的时候,是不是磁盘缓存和内存缓存都有吗?对于这个问题,我们需要理解内存缓存(frommemorycache)和硬盘缓存(fromdiskcache),如下:内存缓存(frommemorycache):内存缓存有两个特点,即快速读取和及时性:fastRead:内存缓存会将编译解析后的文件直接存放到进程的内存中,占用进程一定的内存资源,方便下次运行时快速读取。及时性:进程一旦关闭,进程的内存就会被清除。硬盘缓存(fromdiskcache):硬盘缓存就是直接将缓存写入硬盘文件。读取缓存需要对缓存中存放的硬盘文件进行I/O操作,然后重新解析缓存内容。读取复杂,速度高。比内存缓存慢。在浏览器中,浏览器解析执行后会直接将js、图片等文件存放到内存缓存中,所以页面刷新时,只需要直接从内存缓存(frommemorycache)中读取即可;而css文件会被存入硬盘文件,所以每次渲染页面时,都需要从硬盘(fromdiskcache)中读取缓存。协商缓存协商缓存是指缓存被强制失效后,浏览器向带有缓存标识的服务器发送请求,服务器根据缓存标识决定是否使用缓存。主要有两种情况:协商缓存生效,返回304,协商缓存无效如下,返回200和请求结果,如下,协商缓存的标识也连同返回给浏览器请求结果在响应报文的HTTP头中,控制协商缓存的字段有:Last-Modified/If-Modified-Since和Etag/If-None-Match,其中Etag/If-None-Match具有较高的优先于Last-Modified/If-Modified-Since。Last-Modified/If-Modified-SinceLast-Modified是服务器响应请求的时候,返回资源文件在服务器上最后一次修改的时间,如下。If-Modified-Since表示客户端再次发起请求时,携带上次请求返回的Last-Modified值,通过该字段值告诉服务器上次请求返回的资源的最后修改时间。当服务器收到请求,发现请求头中包含If-Modified-Since字段时,就会将If-Modified-Since字段的值与资源在服务器上的最后修改时间进行比较。如果资源在服务器上的最后修改时间大于If-Modified-Since的字段值,将再次返回该资源,状态码为200;否则返回304,表示资源没有更新,可以继续使用缓存文件,如下。Etag/If-None-MatchEtag是服务器响应请求时返回当前资源文件的唯一标识符(由服务器生成),如下。If-None-Match表示客户端再次发起请求时,携带上次请求返回的唯一标识Etag值,通过该字段值告诉服务端上次请求该资源返回的唯一标识值。服务器收到请求后,发现请求头中包含If-None-Match,就会将If-None-Match的字段值与服务器上资源的Etag值进行比较。如果匹配则返回304,表示资源没有更新。,继续使用缓存文件;如果不一致,则返回状态码为200的资源文件,如下。注意:Etag/If-None-Match的优先级高于Last-Modified/If-Modified-Since,同时存在时只有Etag/If-None-Match生效。摘要强制缓存优先于协商缓存。如果强制缓存(Expires和Cache-Control)生效,则直接使用缓存。如果没有,则进行协商缓存(Last-Modified/If-Modified-SinceandEtag/If-None-Match),协商缓存由服务器决定是否使用缓存。如果协商缓存无效,则说明该请求的缓存无效,重新获取请求结果,存入浏览器缓存;如果生效,则返回304,继续使用缓存。主要流程如下: