<listing id="5l7x1"></listing>

          <listing id="5l7x1"></listing>
            <listing id="5l7x1"><output id="5l7x1"></output></listing>

                <listing id="5l7x1"></listing>

                  <thead id="5l7x1"></thead>

                  <progress id="5l7x1"><output id="5l7x1"></output></progress>

                              <thead id="5l7x1"><output id="5l7x1"><noframes id="5l7x1">

                                <listing id="5l7x1"></listing>
                                <listing id="5l7x1"><b id="5l7x1"><pre id="5l7x1"></pre></b></listing>
                                <thead id="5l7x1"><ol id="5l7x1"><noframes id="5l7x1">

                                <thead id="5l7x1"></thead><thead id="5l7x1"><output id="5l7x1"><noframes id="5l7x1">

                                <thead id="5l7x1"></thead>

                                            浏览器的强缓存和协商缓存

                                            版权声明:本文为博主原创文章,未经博主允许不得转载。 http://www.mwbkrui.tw/GreekMrzzJ/article/details/89738573

                                            浏览器的强缓存和协商缓存

                                            这里说的缓存是指浏览器(客户端)在本地磁盘中对访问过的资源保存的副本文件。

                                            浏览器缓存主要有以下几个优点:

                                            1. 减少重复数据请求,避免通过网络再次加载资源,节省流量。
                                            2. 降低服务器的压力,提升网站性能。
                                            3. 加快客户端加载网页的速度, 提升用户体验。

                                            浏览器缓存分为强缓存和协商缓存,两者有两个比较明显的区别:

                                            1. 如果浏览器命中强缓存,则不需要给服务器发请求;而协商缓存最终由服务器来决定是否使用缓存,即客户端与服务器之间存在一次通信。
                                            2. chrome 中强缓存(虽然没有发出真实的 http 请求)的请求状态码返回是 200 (from cache);而协商缓存如果命中走缓存的话,请求的状态码是 304 (not modified)。 不同浏览器的策略不同,在 Fire Fox中,from cache 状态码是 304.

                                            其中 from cache 会分为 from disk cache 和 from memory cache. 从内存中获取最快,但是是 session 级别的缓存,关闭浏览器之后就没有了。
                                            image.png

                                            请求流程

                                            浏览器在第一次请求后缓存资源,再次请求时,会进行下面两个步骤:

                                            1. 浏览器会获取该缓存资源的 header 中的信息,根据 response header 中的 expirescache-control 来判断是否命中强缓存,如果命中则直接从缓存中获取资源。
                                            2. 如果没有命中强缓存,浏览器就会发送请求到服务器,这次请求会带上 IF-Modified-Since 或者 IF-None-Match, 它们的值分别是第一次请求返回 Last-Modified或者 Etag,由服务器来对比这一对字段来判断是否命中。如果命中,则服务器返回 304 状态码,并且不会返回资源内容,浏览器会直接从缓存获??;否则服务器最终会返回资源的实际内容,并更新 header 中的相关缓存字段。

                                            借用网上的一张图片

                                            image.png

                                            强缓存

                                            强缓存是根据返回头中的 Expires 或者 Cache-Control 两个字段来控制的,都是表示资源的缓存有效时间。

                                            • Expireshttp 1.0 的规范,值是一个GMT 格式的时间点字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT 。这个时间点代表资源失效的时间,如果当前的时间戳在这个时间之前,则判定命中缓存。有一个缺点是,失效时间是一个绝对时间,如果服务器时间与客户端时间偏差较大时,就会导致缓存混乱。而服务器的时间跟用户的实际时间是不一样是很正常的,所以 Expires 在实际使用中会带来一些麻烦。
                                            • Cache-Control这个字段是 http 1.1 的规范,一般常用该字段的 max-age 值来进行判断,它是一个相对时间,比如 .Cache-Control:max-age=3600 代表资源的有效期是 3600 秒。并且返回头中的 Date 表示消息发送的时间,表示当前资源在 Date ~ Date +3600s 这段时间里都是有效的。不过我在实际使用中常常遇到设置了 max-age 之后,在 max-age 时间内重新访问资源却会返回 304 not modified ,这是由于服务器的时间与本地的时间不同造成的。当然 Cache-Control 还有其他几个值可以设置, 不过相对来说都很少用了:
                                              • no-cache 不使用本地缓存。需要使用协商缓存。
                                              • no-store直接禁止浏览器缓存数据,每次请求资源都会向服务器要完整的资源, 类似于 network 中的 disabled cache。
                                              • public 可以被所有用户缓存,包括终端用户和 cdn 等中间件代理服务器。
                                              • private 只能被终端用户的浏览器缓存。

                                            如果 Cache-ControlExpires 同时存在的话, Cache-Control 的优先级高于 Expires 。

                                            协商缓存

                                            协商缓存是由服务器来确定缓存资源是否可用。 主要涉及到两对属性字段,都是成对出现的,即第一次请求的响应头带上某个字, Last-Modified 或者 Etag,则后续请求则会带上对应的请求字段 If-Modified-Since或者 If-None-Match,若响应头没有 Last-Modified 或者 Etag 字段,则请求头也不会有对应的字段。

                                            • Last-Modified/If-Modified-Since 二者的值都是GMT格式的时间字符串, Last-Modified 标记最后文件修改时间, 下一次请求时,请求头中会带上 If-Modified-Since 值就是 Last-Modified 告诉服务器我本地缓存的文件最后修改的时间,在服务器上根据文件的最后修改时间判断资源是否有变化, 如果文件没有变更则返回 304 Not Modified ,请求不会返回资源内容,浏览器直接使用本地缓存。当服务器返回 304 Not Modified 的响应时,response header 中不会再添加的 Last-Modified 去试图更新本地缓存的 Last-Modified, 因为既然资源没有变化,那么 Last-Modified 也就不会改变;如果资源有变化,就正常返回返回资源内容,新的 Last-Modified 会在 response header 返回,并在下次请求之前更新本地缓存的 Last-Modified,下次请求时,If-Modified-Since会启用更新后的 Last-Modified。

                                            • Etag/If-None-Match, 值都是由服务器为每一个资源生成的唯一标识串,只要资源有变化就这个值就会改变。服务器根据文件本身算出一个哈希值并通过 ETag字段返回给浏览器,接收到 If-None-Match 字段以后,服务器通过比较两者是否一致来判定文件内容是否被改变。与 Last-Modified 不一样的是,当服务器返回 304 Not Modified 的响应时,由于在服务器上ETag 重新计算过,response header中还会把这个 ETag 返回,即使这个 ETag 跟之前的没有变化。

                                            HTTP中并没有指定如何生成 ETag,可以由开发者自行生成,哈希是比较理想的选择。

                                            为什么要有 Etag

                                            HTTP1.1Etag 的出现主要是为了解决几个 Last-Modified 比较难解决的问题:

                                            • 一些文件也许会周期性的更改,但是内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
                                            • 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since 能检查到的粒度是秒级的,使用 Etag 就能够保证这种需求下客户端在1秒内能刷新 N 次 cache。
                                            • 某些服务器不能精确的得到文件的最后修改时间。

                                            优先级

                                             Cache-Control  > expires > Etag > Last-Modified
                                            

                                            用户行为对缓存的影响

                                            简单说就是 F5 刷新的时候,会暂时禁用强缓存

                                            经过对qq、fire fox 、safari 、chrome 这几个浏览器的访问同一个页面测试我发现,不同的浏览器在 F5 刷新的时候 ,同一个文件 qq 、fire fox 浏览器会返回 304 Not Nodified,在请求头中不携带 Expires/Cache-Control; 而 chrome 和 safari 刷新的时候,会返回 200 from cache, 没有真正发起请求,走强缓存??杉煌匿榔鞣蠢∈遣灰恢碌?,所以下面表格中"F5刷新"时 Expires/Cache-Control 会无效我认为是存在一定争议的。

                                            而 Ctrl + F5 强制刷新的时候,会暂时禁用强缓存和协商缓存。

                                            在写这篇博客时,对于我仅仅测试了一个浏览器之后便写了无效(因为网上大多数帖子写了无效,我也以为我验证通过了),对指出这个问题的群友,表示感谢,希望其他人不会被我误导。

                                            用户操作 Expires/Cache-Control Last-Modied/Etag
                                            地址栏回车 有效 有效
                                            页面链接跳转 有效 有效
                                            新开窗口 有效 有效
                                            前进回退 有效 有效
                                            F5刷新 无效(有争议,不同浏览器反馈不一致) 有效
                                            Ctrl+F5强制刷新 无效 无效

                                            如何设置强缓存和协商缓存

                                            1. 后端服务器,写入代码逻辑中:

                                              res.setHeader('max-age': '3600 public')
                                              res.setHeader(etag: '5c20abbd-e2e8')
                                              res.setHeader('last-modified': Mon, 24 Dec 2018 09:49:49 GMT)
                                              
                                            2. Nginx 配置

                                              add_header Cache-Control "max-age=3600"
                                              

                                              一般来说,通过 nginx 静态资源服务器,会默认给资源带上强缓存、协商缓存的 header 字段。

                                              image.png

                                            两个示例

                                            1. 如果在 cache-control定义的 max-age 时间之内,js, css 文件会走强缓存,http 状态码是 200, 跟服务器也并不会有交互。但是第一个文件 index.html 文件, 每次回车或者刷新都是状态码都是 304 ,因为它的请求头中默认每次都携带了 Cache-Control: max-age=0 。

                                              image.png

                                              image.png

                                            2. js css 文件 cache-control 超时之后,重新按回车会走协商缓存,请求服务器发现资源没有改变,于是返回 304 ,浏览器从缓存中获取内容,从 size 中也可以看出端倪, 几百 B 的包不是静态资源的体积。

                                              image.png

                                            三级缓存原理(大白话)

                                            最后总结一下浏览器的三级缓存原理:

                                            1. 先去内存看,如果有,直接加载

                                            2. 如果内存没有,择取硬盘获取,如果有直接加载

                                            3. 如果硬盘也没有,那么就进行网络请求

                                            4. 加载到的资源缓存到硬盘和内存

                                            参考文档

                                            from disk cache 与 from memory cache

                                            http协商缓存VS强缓存

                                            没有更多推荐了,返回首页

                                            062期新报跑狗-1谜语 南溪县| 吴江市| 平谷区| 邢台市| 邯郸市| 宜春市| 南丹县| 九龙坡区| 临洮县| 石渠县| 焦作市| 张家川| 屏边| 宁安市| 罗定市| 大关县| 台州市| 高安市| 辽宁省| 崇明县| 江永县| 武川县| 仁怀市| 普陀区| 涪陵区| 勐海县| http://xreptr.cn 石楼县| 新密市| 江山市| 无锡市| 分宜县| 凭祥市| 泾阳县| 莱州市| 南靖县| 德州市| 南宫市| 兴隆县| 博湖县| 高唐县| 平罗县| 孝昌县| 双柏县| 青海省| 项城市| 星座| 高邮市| 息烽县| 普安县| 碌曲县| 丰都县| 天门市| 保亭| 唐河县| 边坝县| http://www.rmjwwd.cn 瑞丽市| 花莲县| 高雄市| 专栏| 江安县| 耒阳市| 孝感市| 图木舒克市| 门头沟区| 梧州市| 苍溪县| 正定县| 南京市| 宝清县| 日土县| 黄平县| 墨江| 谷城县| 南靖县| 乌苏市| 隆安县| 曲周县| 沈阳市| 麻城市| 西城区| 清河县| 礼泉县| 衡南县| 巫溪县| 赞皇县| 广宁县| 阳高县| 上栗县| 高平市| http://www.www.dolnvt.cn 黄石市| 礼泉县| 建昌县| 嘉荫县| 宁化县| 陕西省| 读书| 赫章县| 夏河县| 德惠市| 哈密市| 三河市| 东至县| 潜山县| 龙州县| 鸡东县| 洞头县| 卫辉市| 马龙县| 襄城县| 武平县| 漾濞| 田阳县| 延川县| 怀仁县| 侯马市| 博罗县| 金塔县| 望奎县| http://www.oivikq.cn 郯城县| 高要市| 城市| 隆安县| 漠河县| 成都市| 宁晋县| 蕉岭县| 平武县| 柏乡县| 安义县| 清镇市| 西林县| 广平县| 集安市| 宁夏| 毕节市| 东宁县| 古田县| 墨脱县| 浏阳市| 观塘区| 东台市| 乐业县| 德保县| 申扎县| 长泰县| 清原| 普宁市| http://www.baLancemen.com 永清县| 科尔| 溧阳市| 太谷县| 新晃| 玉溪市| 建昌县| 黄浦区| 利津县| 泰和县| 射洪县| 文昌市| 朝阳县| 福海县| 蒙山县| 大竹县| 常熟市| 新闻| 年辖:市辖区| 泗阳县| 上蔡县| 乳山市| 桦南县| 开阳县| 临海市| 安丘市| 石楼县| 汉阴县| http://www.rnkywf.cn 北京市| 漾濞| 阿图什市| 扎赉特旗| 手游| 阜康市| 久治县| 石台县| 诸暨市| 固原市| 泗水县| 泾川县| 本溪市| 三门县| 黄骅市| 二连浩特市| 运城市|