浅谈 http 缓存

前言

浏览器缓存的方式有很多种,打开 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 那里把 前面打上勾,就可以禁止缓存了

可以尝试在浏览器的无痕模式下进行开发或者做其它事情 ^_^ 嘿嘿 ~

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181010G23WCA00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券