10分钟彻底搞懂Http的强制缓存和协商缓存(小结)


Posted in Javascript onAugust 30, 2018

浏览器缓存

浏览器缓存是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档。

所以根据上面的特点,浏览器缓存有下面的优点:

  • 减少冗余的数据传输
  • 减少服务器负担
  • 加快客户端加载网页的速度

浏览器缓存是Web性能优化的重要方式。那么浏览器缓存的过程究竟是怎么样的呢?

在浏览器第一次发起请求时,本地无缓存,向web服务器发送请求,服务器起端响应请求,浏览器端缓存。过程如下:

在第一次请求时,服务器会将页面最后修改时间通过Last-Modified标识由服务器发送给客户端,客户端记录修改时间;服务器还会生成一个Etag,并发送给客户端。

浏览器后续再次进行请求时:

浏览器缓存主要分为强强缓存(也称本地缓存)和协商缓存(也称弱缓存)。根据上图,浏览器在第一次请求发生后,再次发送请求时:

  • 浏览器请求某一资源时,会先获取该资源缓存的header信息,然后根据header中的Cache-Control和Expires来判断是否过期。若没过期则直接从缓存中获取资源信息,包括缓存的header的信息,所以此次请求不会与服务器进行通信。这里判断是否过期,则是强缓存相关。后面会讲Cache-Control和Expires相关。
  • 如果显示已过期,浏览器会向服务器端发送请求,这个请求会携带第一次请求返回的有关缓存的header字段信息,比如客户端会通过If-None-Match头将先前服务器端发送过来的Etag发送给服务器,服务会对比这个客户端发过来的Etag是否与服务器的相同,若相同,就将If-None-Match的值设为false,返回状态304,客户端继续使用本地缓存,不解析服务器端发回来的数据,若不相同就将If-None-Match的值设为true,返回状态为200,客户端重新机械服务器端返回的数据;客户端还会通过If-Modified-Since头将先前服务器端发过来的最后修改时间戳发送给服务器,服务器端通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回最新的内容,如果是最新的,则返回304,客户端继续使用本地缓存。

一 强制缓存

强制缓存整体流程比较简单,就是在第一次访问服务器取到数据之后,在过期时间之内不会再去重复请求。实现这个流程的核心就是如何知道当前时间是否超过了过期时间。

强制缓存的过期时间通过第一次访问服务器时返回的响应头获取。在 http 1.0 和 http 1.1 版本中通过不同的响应头字段实现。

http 1.0

在 http 1.0 版本中,强制缓存通过 Expires 响应头来实现。 expires 表示未来资源会过期的时间。也就是说,当发起请求的时间超过了 expires 设定的时间,即表示资源缓存时间到期,会发送请求到服务器重新获取资源。而如果发起请求的时间在 expires 限定的时间之内,浏览器会直接读取本地缓存数据库中的信息(from memory or from disk),两种方式根据浏览器的策略随机获取。

http 1.1

在 http 1.1 版本中,强制缓存通过 Cache-Control 响应头来实现。Cache-Control 拥有多个值:

  • private:客户端可以缓存
  • public:客户端和代理服务器均可缓存;
  • max-age=xxx:缓存的资源将在 xxx 秒后过期;
  • no-cache:需要使用协商缓存来验证是否过期;
  • no-store:不可缓存

最常用的字段就是 max-age=xxx ,表示缓存的资源将在 xxx 秒后过期。一般来说,为了兼容,两个版本的强制缓存都会被实现。

总结

强制缓存只有首次请求才会跟服务器通信,读取缓存资源时不会发出任何请求,资源的 Status 状态码为 200,资源的 Size 为 from memory 或者 from disk ,http 1.1 版本的实现优先级会高于 http 1.0 版本的实现。

二 协商缓存

协商缓存与强制缓存的不同之处在于,协商缓存每次读取数据时都需要跟服务器通信,并且会增加缓存标识。在第一次请求服务器时,服务器会返回资源,并且返回一个资源的缓存标识,一起存到浏览器的缓存数据库。当第二次请求资源时,浏览器会首先将缓存标识发送给服务器,服务器拿到标识后判断标识是否匹配,如果不匹配,表示资源有更新,服务器会将新数据和新的缓存标识一起返回到浏览器;如果缓存标识匹配,表示资源没有更新,并且返回 304 状态码,浏览器就读取本地缓存服务器中的数据。

在 http 协议的 1.0 和 1.1 版本中也有不同的实现方式。

http 1.0

在 http 1.0 版本中,第一次请求资源时服务器通过 Last-Modified 来设置响应头的缓存标识,并且把资源最后修改的时间作为值填入,然后将资源返回给浏览器。在第二次请求时,浏览器会首先带上 If-Modified-Since 请求头去访问服务器,服务器会将 If-Modified-Since 中携带的时间与资源修改的时间匹配,如果时间不一致,服务器会返回新的资源,并且将 Last-Modified 值更新,作为响应头返回给浏览器。如果时间一致,表示资源没有更新,服务器返回 304 状态码,浏览器拿到响应状态码后从本地缓存数据库中读取缓存资源。

这种方式有一个弊端,就是当服务器中的资源增加了一个字符,后来又把这个字符删掉,本身资源文件并没有发生变化,但修改时间发生了变化。当下次请求过来时,服务器也会把这个本来没有变化的资源重新返回给浏览器。

http 1.1

在 http 1.1 版本中,服务器通过 Etag 来设置响应头缓存标识。Etag 的值由服务端生成。在第一次请求时,服务器会将资源和 Etag 一并返回给浏览器,浏览器将两者缓存到本地缓存数据库。在第二次请求时,浏览器会将 Etag 信息放到 If-None-Match 请求头去访问服务器,服务器收到请求后,会将服务器中的文件标识与浏览器发来的标识进行对比,如果不相同,服务器返回更新的资源和新的 Etag ,如果相同,服务器返回 304 状态码,浏览器读取缓存。

总结

协商缓存每次请求都会与服务器交互,第一次是拿数据和标识的过程,第二次开始,就是浏览器询问服务器资源是否有更新的过程。每次请求都会传输数据,如果命中缓存,则资源的 Status 状态码为 304 而不是 200 。同样的,一般来讲为了兼容,两个版本的协商缓存都会被实现,http 1.1 版本的实现优先级会高于 http 1.0 版本的实现。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Lazy Load 延迟加载图片的jQuery插件中文使用文档
Oct 18 Javascript
JavaScript实现网页对象拖放功能的方法
Apr 15 Javascript
jQuery中(function($){})(jQuery)详解
Jul 15 Javascript
jquery实现文本框的禁用和启用
Dec 07 Javascript
Jquery Easyui菜单组件Menu使用详解(15)
Dec 18 Javascript
微信小程序中form 表单提交和取值实例详解
Apr 20 Javascript
详解node服务器中打开html文件的两种方法
Sep 18 Javascript
用Webpack构建Vue项目的实践
Nov 07 Javascript
vue在手机中通过本机IP地址访问webApp的方法
Aug 15 Javascript
对layui中表单元素的使用详解
Aug 15 Javascript
生成无限制的微信小程序码的示例代码
Sep 20 Javascript
React自定义hook的方法
Jun 25 Javascript
解决jQuery使用append添加的元素事件无效的问题
Aug 30 #jQuery
jsonp跨域及实现百度首页联想功能的方法
Aug 30 #Javascript
解决使用bootstrap的dropdown部件时报错:error:Bootstrap dropdown require Popper.js问题
Aug 30 #Javascript
解决vue的变量在settimeout内部效果失效的问题
Aug 30 #Javascript
JS+HTML5 Canvas实现简单的写字板功能示例
Aug 30 #Javascript
详解React native fetch遇到的坑
Aug 30 #Javascript
对Vue2 自定义全局指令Vue.directive和指令的生命周期介绍
Aug 30 #Javascript
You might like
php使用curl详细解析及问题汇总
2016/08/11 PHP
php实现文件上传基本验证
2020/03/04 PHP
当jQuery遭遇CoffeeScript的时候 使用分享
2011/09/17 Javascript
在表单提交前进行验证的几种方式整理
2013/07/31 Javascript
jquery 清空file域示例(兼容个浏览器)
2013/10/11 Javascript
jQuery获取页面及个元素高度、宽度的总结——超实用
2015/07/28 Javascript
jQuery深拷贝Json对象简单示例
2016/07/06 Javascript
Javascript中indexOf()和lastIndexOf应用方法实例
2016/08/24 Javascript
JS实现隐藏同级元素后只显示JS文件内容的方法
2016/09/04 Javascript
JS条形码(一维码)插件JsBarcode用法详解【编码类型、参数、属性】
2017/04/19 Javascript
详解Node使用Puppeteer完成一次复杂的爬虫
2018/04/18 Javascript
微信小程序实现美团菜单
2018/06/06 Javascript
JavaScript捕捉事件和阻止冒泡事件实例分析
2018/08/03 Javascript
深入理解js A*寻路算法原理与具体实现过程
2018/12/13 Javascript
element-ui 远程搜索组件el-select在项目中组件化的实现代码
2019/12/04 Javascript
关于element的表单组件整理笔记
2021/02/05 Javascript
Python随机生成均匀分布在单位圆内的点代码示例
2017/11/13 Python
解决pycharm界面不能显示中文的问题
2018/05/23 Python
python 在某.py文件中调用其他.py内的函数的方法
2019/06/25 Python
如何使用Python自动控制windows桌面
2019/07/11 Python
TensorFlow实现打印每一层的输出
2020/01/21 Python
Python实现图片查找轮廓、多边形拟合、最小外接矩形代码
2020/07/14 Python
python如何实现DES加密
2020/09/21 Python
HTML5实现预览本地图片
2016/02/17 HTML / CSS
移动HTML5前端框架—MUI的使用
2017/12/18 HTML / CSS
英国独特礼物想法和个性化礼物网站:notonthehighstreet.com
2018/04/16 全球购物
万代美国官网:PREMIUM BANDAI USA
2020/09/11 全球购物
Linux Interview Questions For software testers
2013/05/17 面试题
创先争优承诺书范文
2014/03/31 职场文书
四风批评与自我批评范文
2014/10/14 职场文书
经费申请报告
2015/05/15 职场文书
三傻大闹宝莱坞观后感
2015/06/03 职场文书
婚庆开业庆典主持词
2015/06/30 职场文书
2016春季田径运动会广播稿
2015/12/21 职场文书
pytorch 使用半精度模型部署的操作
2021/05/24 Python
用python基于appium模块开发一个自动收取能量的小助手
2021/09/25 Python