一文读懂http缓存(超详细)

东方客主 等级 384 0 0

前端缓存

前端缓存可分为两大类:http缓存和浏览器缓存。我们今天重点讲的是http缓存,所以关于浏览器缓存大家自行去查阅。下面这张图是前端缓存的一个大致知识点:

一文读懂http缓存(超详细)

image

HTTP缓存

首先是解决困扰人们的老大难问题:

一、什么是HTTP缓存 ?

http缓存指的是: 当客户端向服务器请求资源时,会先抵达浏览器缓存,如果浏览器有“要请求资源”的副本,就可以直接从浏览器缓存中提取而不是从原始服务器中提取这个资源。

常见的http缓存只能缓存get请求响应的资源,对于其他类型的响应则无能为力,所以后续说的请求缓存都是指GET请求。

http缓存都是从第二次请求开始的。第一次请求资源时,服务器返回资源,并在respone header头中回传资源的缓存参数;第二次请求时,浏览器判断这些请求参数,命中强缓存就直接200,否则就把请求参数加到request header头中传给服务器,看是否命中协商缓存,命中则返回304,否则服务器会返回新的资源。

1、http缓存的分类:
根据是否需要重新向服务器发起请求来分类,可分为(强制缓存,协商缓存) 根据是否可以被单个或者多个用户使用来分类,可分为(私有缓存,共享缓存) 强制缓存如果生效,不需要再和服务器发生交互,而协商缓存不管是否生效,都需要与服务端发生交互。下面是强制缓存和协商缓存的一些对比:

一文读懂http缓存(超详细)

image

1.1、强制缓存
强制缓存在缓存数据未失效的情况下(即Cache-Control的max-age没有过期或者Expires的缓存时间没有过期),那么就会直接使用浏览器的缓存数据,不会再向服务器发送任何请求。强制缓存生效时,http状态码为200。这种方式页面的加载速度是最快的,性能也是很好的,但是在这期间,如果服务器端的资源修改了,页面上是拿不到的,因为它不会再向服务器发请求了。这种情况就是我们在开发种经常遇到的,比如你修改了页面上的某个样式,在页面上刷新了但没有生效,因为走的是强缓存,所以Ctrl + F5一顿操作之后就好了。 跟强制缓存相关的header头属性有(Pragma/Cache-Control/Expires)

一文读懂http缓存(超详细)

image

这个Pragma和Cache-Control共存时的优先级问题还有点异议,我在不同的文章里发现:有的说Pragma的优先级更高,有的说Cache-Control高。为了搞清楚这个问题,我决定动手操作一波,首先我用nodejs搭建后台服务器,目的是设置缓存参数,具体代码如下:

一文读懂http缓存(超详细)

image

然后再浏览器上访问:http://localhost:8888
第一次访问时都是从后台返回的数据:

一文读懂http缓存(超详细)

image

第二次访问时:

一文读懂http缓存(超详细)

image

一文读懂http缓存(超详细)

image

最终得出结论:
Pragma和Cache-control共存时,Pragma的优先级是比Cache-Control高的。

注意:
在chrome浏览器中返回的200状态会有两种情况:
1、from memory cache
(从内存中获取/一般缓存更新频率较高的js、图片、字体等资源)

2、from disk cache
(从磁盘中获取/一般缓存更新频率较低的js、css等资源)

这两种情况是chrome自身的一种缓存策略,这也是为什么chrome浏览器响应的快的原因。其他浏览返回的是已缓存状态,没有标识是从哪获取的缓存。

chrome浏览器:

一文读懂http缓存(超详细)

image

Firefox浏览器:

一文读懂http缓存(超详细)

image

1.2、协商缓存
当第一次请求时服务器返回的响应头中没有Cache-Control和Expires或者Cache-Control和Expires过期还或者它的属性设置为no-cache时(即不走强缓存),那么浏览器第二次请求时就会与服务器进行协商,与服务器端对比判断资源是否进行了修改更新。如果服务器端的资源没有修改,那么就会返回304状态码,告诉浏览器可以使用缓存中的数据,这样就减少了服务器的数据传输压力。如果数据有更新就会返回200状态码,服务器就会返回更新后的资源并且将缓存信息一起返回。跟协商缓存相关的header头属性有(ETag/If-Not-Match 、Last-Modified/If-Modified-Since)请求头和响应头需要成对出现

一文读懂http缓存(超详细)

image

协商缓存的执行流程是这样的:当浏览器第一次向服务器发送请求时,会在响应头中返回协商缓存的头属性:ETag和Last-Modified,其中ETag返回的是一个hash值,Last-Modified返回的是GMT格式的最后修改时间。然后浏览器在第二次发送请求的时候,会在请求头中带上与ETag对应的If-Not-Match,其值就是响应头中返回的ETag的值,Last-Modified对应的If-Modified-Since。服务器在接收到这两个参数后会做比较,如果返回的是304状态码,则说明请求的资源没有修改,浏览器可以直接在缓存中取数据,否则,服务器会直接返回数据。

一文读懂http缓存(超详细)

image

一文读懂http缓存(超详细)

image

注意:
ETag/If-Not-Match是在HTTP/1.1出现的,主要是解决以下问题:

(1)、Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间

(2)、如果某些文件被修改了,但是内容并没有任何变化,而Last-Modified却改变了,导致文件没法使用缓存

(3)、有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形

1.3、私有缓存(浏览器级缓存)
私有缓存只能用于单独的用户:Cache-Control: Private

1.4、共享缓存(代理级缓存)
共享缓存可以被多个用户使用: Cache-Control: Public

二、为什么要使用HTTP缓存 ?

根据上面的学习可发现使用缓存的好处主要有以下几点:
1. 减少了冗余的数据传输,节省了网费。
2. 缓解了服务器的压力, 大大提高了网站的性能
3. 加快了客户端加载网页的速度

三、如何使用HTTP缓存 ?

一般需要缓存的资源有html页面和其他静态资源:
1、html页面缓存的设置主要是在标签中嵌入标签,这种方式只对页面有效,对页面上的资源无效
1.1、html页面禁用缓存的设置如下:

// 仅有IE浏览器才识别的标签,不一定会在请求字段加上Pragma,但的确会让当前页面每次都发新请求 // 其他主流浏览器识别的标签 // 仅有IE浏览器才识别的标签,该方式仅仅作为知会IE缓存时间的标记,你并不能在请求或响应报文中找到Expires字段

1.2、html设置缓存如下:

// 其他主流浏览器识别的标签 // 仅有IE浏览器才识别的标签

2、静态资源的缓存一般是在web服务器上配置的,常用的web服务器有:nginx、apache。具体的配置这里不做详细介绍,大家自行查阅。

3、不想使用缓存的几种方式:
3.1、Ctrl + F5强制刷新,都会直接向服务器提取数据。
3.2、按F5刷新或浏览器的刷新按钮,默认加上Cache-Control:max-age=0,即会走协商缓存。
3.2、在IE浏览器下不想使用缓存的做法:打开IE,点击工具栏上的工具->Internet选项->常规->浏览历史记录 设置. 选择“从不”,然后保存。最后点击“删除”把Internet临时文件都删掉 (IE缓存的文件就是Internet临时文件)。
3.3、还有就是上面1、2中禁用缓存的做法
3.4、对于其他浏览器也都有清除缓存的办法

四、HTTP缓存的几个注意点

1、强缓存情况下,只要缓存还没过期,就会直接从缓存中取数据,就算服务器端有数据变化,也不会从服务器端获取了,这样就无法获取到修改后的数据。决解的办法有:在修改后的资源加上随机数,确保不会从缓存中取。

例如:
http://www.kimshare.club/kim/common.css?v=22324432
http://www.kimshare.club/kim/common.2312331.css

2、尽量减少304的请求,因为我们知道,协商缓存每次都会与后台服务器进行交互,所以性能上不是很好。从性能上来看尽量多使用强缓存。

3、在Firefox浏览器下,使用Cache-Control: no-cache 是不生效的,其识别的是no-store。这样能达到其他浏览器使用Cache-Control: no-cache的效果。所以为了兼容Firefox浏览器,经常会写成Cache-Control: no-cache,no-store。

4、与缓存相关的几个header属性有:Vary、Date/Age。
Vary:
vary本身是“变化”的意思,而在http报文中更趋于是“vary from”(与。。。不同)的含义,它表示服务端会以什么基准字段来区分、筛选缓存版本。
在服务端有着这么一个地址,如果是IE用户则返回针对IE开发的内容,否则返回另一个主流浏览器版本的内容。
格式:Vary: User-Agent
知会代理服务器需要以 User-Agent 这个请求首部字段来区别缓存版本,防止传递给客户端的缓存不正确。

Date/Age:
响应报文中的 Date 和 Age 字段:区分其收到的资源是否命中了代理服务器的缓存。
Date 理所当然是原服务器发送该资源响应报文的时间(GMT格式),如果你发现 Date 的时间与“当前时间”差别较大,或者连续F5刷新发现 Date 的值都没变化,则说明你当前请求是命中了代理服务器的缓存。
Age 也是响应报文中的首部字段,它表示该文件在代理服务器中存在的时间(秒),如文件被修改或替换,Age会重新由0开始累计。

浏览器缓存

下面说说最常用到的浏览器缓存有:cookie、sessionStorage、localStorage这三者的主要特征如下:

一文读懂http缓存(超详细)

image

课程总结

1、对于强制缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时间内,执行协商缓存策略。

2、对于协商缓存,将缓存信息中的Etag和Last-Modified通过请求发送给服务器,由服务器校验,返回304状态码时,浏览器直接使用缓存。

下图是浏览器首次和再次发送http请求的执行流程图:

一文读懂http缓存(超详细)

image

一文读懂http缓存(超详细)image

这是我在整理http缓存过程中总结的知识点,希望对大家有帮助!由于能力有限,如有纠正之处,欢迎留言指出

本文转自 https://www.jianshu.com/p/227cee9c8d15,如有侵权,请联系删除。

收藏
评论区

相关推荐

前端开发中79条不可忽视的知识点汇总
过往一些不足的地方,通过博客,好好总结一下。 1.css禁用鼠标事件 css .disabled { pointerevents: none; cursor: default; opacity: 0.6; } 2.get/post的理解和他们之间的区别 http 超文本传输协议(HTTP)的设计目的是保证客户机
HTTP 的本质?HTTP 和 RPC 的区别?
身为 Java Web 开发我发现很多人一些 Web 基础问题都答不上来。 上周我面试了一个三年经验的小伙子,一开始我问他 HTTP/1、HTTP/2相关的他到是能答点东西出来。 后来我问他:你怎么理解 HTTP 的,HTTP 的作用是什么? 他支支吾吾答不出来。 经过了一番引导交谈,他回答是用来客户端和服务端之间传输的。 我接着问那你知道什么是
Appium+python自动化(二)- 环境搭建—下(超详解)
Appiumpython自动化(二) 环境搭建—下(超详解) Appiumpython自动化(二) 环境搭建—下(超详解) 简介    宏哥的人品还算说得过去,虽然很久没有
django搭建web小项目
创建项目 原文1:http://blog.csdn.net/yjx2323999451/article/details/53200243(http://blog.csdn.net/yjx2323999451/article/details/53200243) 原文2:http://www.cnblogs.com/benshan/p/4445074.
一文搞懂什么是HTTP与HTTPS
(https://blog.csdn.net/petterp/article/details/102779257)Http与Https的区别。 在最近的开发中,深感网络相关基础知识薄弱,于是趁周末好好总结一
Http协议详解
超文本传输协议 请求/响应报文 连接建立的流程 HTTP的特点 请求/响应报文 请求报文 (https://imghelloworld.osscnbeijing.aliyuncs.com/146ca2b87d6a82b2c5c101154d9
HTTP面试题精选_langsiming的博客
1. 简述下TCP三次握手的过程,并解释采用3次握手建立连接的原因? 1. 客户端发送建立连接请求,携带信息syn 1,seq X 第一次握手 2.
一文读懂http缓存(超详细)
前端缓存 前端缓存可分为两大类:http缓存和浏览器缓存。我们今天重点讲的是http缓存,所以关于浏览器缓存大家自行去查阅。下面这张图是前端缓存的一个大致知识点: (https://imghelloworld.osscnbeijing.aliyuncs.com/3e161cfcbe560b9608064ec91077346
「查缺补漏」巩固你的HTTP知识体系
前言这次梳理的篇幅主要是涉及网络部分,包括HTTP等,对巩固自己的网络知识体系也是很有帮助的,进一步的对性能优化而言也是帮助很大的。但更多的是抛砖引玉,希望对你们有所帮助。接下来就以问题的形式展开梳理👇谈一谈HTTP协议优缺点超文本传输协议,「HTTP 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的
【Flutter实战】流式布局(Wrap、Flow)
4.4 流式布局在介绍Row和Colum时,如果子widget超出屏幕范围,则会报溢出错误,如:dartRow( children: <Widget Text("xxx"100) ,);可以看到,右边溢出部分报错。这是因为Row默认只有一行,如果超出屏幕不会折行。我们把超出屏幕显示范围会自动折行的布局称为流式布局。Flutt
5分钟快速梳理你的HTTP体系
HTTP 定义 1. HTTP(超文本传输协议) 是 客户端 与 服务端 之间信息交流的 桥梁。 2. 在信息交流之前必须要做的就是 客户端通过连接TCP/IP协议 80 端口 ,以便 服务端侦听HTTP请求。 3.HTTP 是 一种通用的 , 无状态的应用层协议,基于标准客户机/服务器模型。 HTTP 特点 1.采用 “请求/
[前端必知 ]HTTP or TCP/IP 基础
<section id"nice" datatool"mdnice编辑器" datawebsite"https://www.mdnice.com" style"fontsize: 16px; padding: 0 10px; wordspacing: 0px; wordbreak: breakword; wordwrap: break
list assignment index out of range
分析:list assignment index out of range:列表超过限制一种情况是:list[index]index超出范围另一种情况是:list是一个空的,没有一个元素,进行list[0]就会出现错误!
「超全超细」Java设计模式图文详解!!!
java设计模式—原型模式 Java原型模式 1、概述  啥是原型模式?  原型模式属于设计模式中的创建型中的一员,  原型模式:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象!  说大白话就是自己复制自己,通过原生对象复制出一个新的对象,这两个对象结构相同且相似;  需要注意的是,原型对象自己不仅是个对象还是个工厂!并且通过克隆方式创
Excel中的xls、xlsx、xlsm混合文件,看我用Python如何统一处理......
引言Python语言,近几年在办公自动化这一领域来说,真的超级火爆!用它做批量处理确实比VBA要方便很多。前面的文章,我们已经讲述了如何将doc文件转换为docx文件,还没有观看的朋友直接戳此链接:](http://mp.weixin.qq.com/s?bizMzkwNDE5NTc0Ng&mid2247514428&idx1&sn1f8720112f6a88