前言
浏览器缓存的方式有很多种,打开 Chrome 的控制台,点击 Application 模块,我们可以看到左侧的列表部分,它们其实就对应着浏览器的各种缓存机制。其中的 Frames 模块就是本文所要介绍的,也就是 http 缓存。当然,平时我们写代码时可能不用太操心这个东西,因为浏览器会自己搞定的,不过要知道有这么回事,万一哪天要用到呢。
什么是 http 缓存
比较官方的解释:http 缓存就是基于 http 协议的浏览器文件级缓存机制。
通俗来讲:就是当我们随便打开一个页面,浏览器就会自动的把页面缓存到本地,具体来说就是把该页面的某些资源(js、css和图片等)另存为到本地(也就是备份),下次当我们再访问该页面的时候,浏览器就可以从本地读取该页面的资源,缩短页面响应时间。
为什么要 http 缓存
缩短页面响应时间(就是快啦),用户体验就蹭蹭蹭的上升
减少对源服务器的请求,服务器的压力也因此降低
爬虫能根据过期机制降低爬取的频率,提高爬虫效率
减小网络带宽损耗,为用户和运营者剩下了一笔钱
需要了解的状态码
相当于第一次请求
无请求,直接使用缓存
有一次请求,发现资源未被更新,然后再使用缓存
需要了解的 Headers 信息
缓存过期时间( Expires )
形如:
另一个缓存过期时间( Cache-Control )
形如:
文件的最后修改时间( Last-Modified )
形如:
根据页面内容计算出来的实体标记( Etag )
形如: 或 等
http 缓存的过程
第一步:打开浏览器,在地址栏输入某个 并回车,这时候由于是首次访问页面,所以没有缓存,浏览器就直接向服务器发送请求,打开控制台我们能够看到服务器会返回 的状态码,以及一些响应头信息如:、、 和 ,同时浏览器会把该路径下的文件缓存到本地。
第二步:当我们再次访问该 时,因为本地已经有了缓存(也就是备份),所以就暂且先不发送请求到服务器,而是到本地寻找缓存文件,看能不能用。这里的判断过程会按照如下顺序进行:
先判断 `Expires` 和 `Cache-Control`:
a) 未过期 => 不发http请求,直接读取http缓存文件,打开控制台我们能看到返回的状态码是 。(也称作强缓存)
b) 已过期 => 向服务器发送请求,并带上之前的 (放在 字段里)和 (放在 字段里)信息
注意:如果两者同时存在, 的优先级高于 ,也就是忽略 。
再判断 `Last-Modified` 和 `Etag`:
a) 若两者都没有变化,则服务器会返回 的状态码,以此来告知浏览器资源未被更新,你那边的缓存还能用,于是浏览器就会到本地缓存中去取对应的内容,期间浏览器和服务器有一次请求(又称作协商缓存或对比缓存)
b) 若两者有任何一个被改变,则服务器会受理此次请求,返回 ,就像第一次请求那样
注意:如果两者同时存在, 的优先级高于 ,也就是先判断 。
你可能会有的疑问
为什么有了 还要 ?
因为响应报文中 所定义的过期时间是相对服务器而言的,要是服务器和客户端的时间不一样(比如用户自己修改了电脑的系统时间),缓存就会出现偏差。所以为了解决这个问题, 就出现了,可以理解为是对 的补充,使用的是相对时间(以秒为单位),是 Http1.1 中的标准,而 是 Http1.0 中的标准。
注意:若 和 同时出现,则以 为准。
为什么有了 还要 ?
因为 HTTP1.1 中 的出现主要是为了解决 解决不了的问题:比如我们在1秒内多次修改某个文件,由于 的时间只能记录到秒级,所以它将不能正确表示文件的修改时间;又或者文件内容没有变化而 改变了,我们也使用不了缓存。
注意:若两者同时存在,服务器会优先对比 ,验证通过的情况下才会继续比较 ,最后才决定是否返回 。
不也发送了请求吗,为什么会快?
虽然 也发送了一次请求,但服务器只会返回报文的头部信息,主体部分将不会返回,报文的大小和请求时间大大减少,于是就快了。
http 缓存的不同来源
(从磁盘中获取缓存资源)
(从内存中获取资源)
注意:当退出进程时,磁盘的数据不会被清空,而内存会。
不同的刷新方式
通过链接、前进、后退或者地址栏访问,会先判断缓存是否过期(也就是先判断 / ),再判断缓资源是否更新( / )
在打开控制台的情况下,长按刷新图标(1-2秒),选择相应的刷新方式即可
通过 F5 刷新,会忽略 / 的设置(其实是加上了 的请求字段),然后向服务器发送请求,而 / 还是有效的,服务器会根据情况判断返回 还是
通过 Ctrl+F5 进行强制刷新的时候,缓存将失效,会重新向服务器请求资源(当然不同浏览器和不同操作系统的刷新操作可能不一样)
需要注意的是
post 请求和经过 https 安全加密的请求不会被缓存
这个很容易让人误以为是响应不被缓存(我就是这样认为的)。实际上 是会把数据缓存到本地的,只不过会被浏览器忽略,重新向服务器获取文件。而 这个才是响应不被缓存的意思
对于同一个资源,不同服务器生成的 可能不相同(生成规则由服务器决定,当然你可以自己修改服务器端 的生成方式)
资源更新时,为防止用户获取信息不及时,我们可以在资源 后面附加一些信息,如版本号、md5 和修改时间等
小技巧
打开 Chrome 浏览器,地址栏输入 chrome://cache 回车,就能看到 Chrome 浏览器缓存的文件
打开控制台,在 Network 那里把 前面打上勾,就可以禁止缓存了
可以尝试在浏览器的无痕模式下进行开发或者做其它事情 ^_^ 嘿嘿 ~
领取专属 10元无门槛券
私享最新 技术干货