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 相关文章推荐
JavaScript 组件之旅(一)分析和设计
Oct 28 Javascript
jQuery的.live()和.die() 使用介绍
Sep 10 Javascript
javascript获取URL参数与参数值的示例代码
Dec 20 Javascript
JS不能跨域借助jquery获取IP地址的方法
Aug 20 Javascript
轻松学习jQuery插件EasyUI EasyUI创建CRUD应用
Nov 30 Javascript
JavaScript+html5 canvas制作的百花齐放效果完整实例
Jan 26 Javascript
在Javascript操作JSON对象,增加 删除 修改的简单实现
Jun 02 Javascript
JS针对浏览器窗口关闭事件的监听方法集锦
Jun 24 Javascript
jquery配合.NET实现点击指定绑定数据并且能够一键下载
Oct 28 Javascript
浅谈js之字面量、对象字面量的访问、关键字in的用法
Nov 20 Javascript
javascript实现文字无缝滚动
Dec 27 Javascript
vue 地区选择器v-distpicker的常用功能
Jul 23 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开发文件系统实例讲解
2006/10/09 PHP
PHP用mysql数据库存储session的代码
2010/03/05 PHP
php去除html标记的原生函数详解
2015/01/27 PHP
PHP使用http_build_query()构造URL字符串的方法
2016/04/02 PHP
很多人都是用下面的js刷新站IP和PV
2008/09/05 Javascript
js function使用心得
2010/05/10 Javascript
判断浏览器的javascript版本的代码
2010/09/03 Javascript
js 针对html DOM元素操作等经验累积
2014/03/11 Javascript
jquery实现简单的自动播放幻灯片效果
2015/06/13 Javascript
浅谈jquery中delegate()与live()
2015/06/22 Javascript
常见JS验证脚本汇总
2015/12/01 Javascript
js实现input密码框提示信息的方法(附html5实现方法)
2016/01/14 Javascript
CSS或者JS实现鼠标悬停显示另一元素
2016/01/22 Javascript
关于获取DIV内部内容报错的原因分析及解决办法
2016/01/29 Javascript
浅谈JS读取DOM对象(标签)的自定义属性
2016/11/21 Javascript
vue实现点击图片放大效果
2017/08/15 Javascript
快速解决select2在bootstrap模态框中下拉框隐藏的问题
2018/08/10 Javascript
微信小程序如何实现全局重新加载
2019/06/05 Javascript
基于jquery ajax的多文件上传进度条过程解析
2019/09/11 jQuery
vue的路由映射问题及解决方案
2019/10/14 Javascript
webpack4 配置 ssr 环境遇到“document is not defined”
2019/10/24 Javascript
如何利用nodejs自动定时发送邮件提醒(超实用)
2020/12/01 NodeJs
利用Python自带PIL库扩展图片大小给图片加文字描述的方法示例
2017/08/08 Python
python 协程中的迭代器,生成器原理及应用实例详解
2019/10/28 Python
在 Linux/Mac 下为Python函数添加超时时间的方法
2020/02/20 Python
IntelliJ 中配置 Anaconda的过程图解
2020/06/01 Python
深入解读CSS3中transform变换模型的渲染
2016/05/27 HTML / CSS
Bench加拿大官方网站:英国城市服装品牌
2017/11/03 全球购物
Exception类的常用方法
2012/06/16 面试题
大学学年自我鉴定
2013/10/28 职场文书
企业管理部经理岗位职责
2013/12/24 职场文书
大学生个人事迹材料
2014/01/21 职场文书
“九一八事变纪念日”国旗下讲话稿
2014/09/14 职场文书
2016七夕情人节寄语
2015/12/04 职场文书
vue项目配置sass及引入外部scss文件
2022/04/14 Vue.js
Win10 最新稳定版本 21H2开始推送
2022/04/19 数码科技