缓存——浏览器缓存

3,069 阅读5分钟

一.概述

  • 浏览器缓存即http缓存,将数据缓存在浏览器(即客户端)。
  • 服务端通过设置HTTP响应头来决定缓存策略,将资源缓存到本地浏览器。

二.工作流程

http缓存都是从第二次请求开始的。

  • 第一次请求资源,服务器返回对应资源,并在response header响应头中添加缓存策略。
  • 第二次请求时,浏览器判断请求参数,命中强缓存就直接200,从本地缓存中拿数据。否则把响应参数存在request header请求头中,看是否命中协商缓存,命中则返回304,否则服务器会返回全新资源。

强缓存与协商缓存

  • 强缓存:无需与服务端发生交互
  • 协商缓存:需要与服务端发生交互,判断是否使用本地缓存的文件。

三.缓存示例

  • 无缓存:
  • 协商缓存:
  • 强缓存: 分析
  • 无缓存时,状态码200,传输size为6.9MB,传输时间8.63s。
  • 设置协商缓存后,状态码304,传输size为350B,时间100ms,造成差异的原因时协商缓存发送的是304请求判断是否使用本地缓存,如果缓存命中,浏览器直接从本地拿缓存的文件,6.9MB的文件就不需要走网络传输了,因此响应时间会极大的缩短。
  • 设置强缓存,传输时间为0ms。因为不需要走网络传输了,直接走本地缓存,因此响应时间为0。

四.几个控制缓存策略的响应头

强缓存

4.1 Expires

Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求的结果缓存的到期时间,即再次发送请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。 到了HTTP/1.1,Expires已经被Cache-Control替代,原因在于Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,如果客户端与服务端的时间由于某些原因(时区不同;客户端和服务端有一方的时间不准确)发生误差,那么强制缓存将直接失效

4.2 Cache-Control

在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存,主要取值为:

  • public:所有内容都将被缓存(客户端和代理服务器都可缓存)
  • private:所有内容只有客户端可以缓存,Cache-Control的默认取值
  • no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
  • no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
  • max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效
  • must-revalidate:告诉浏览器、缓存服务器,本地副本过期前,可以使用本地副本;本地副本一旦过期,必须去源服务器进行有效性校验。

在无法确定客户端的时间是否与服务端的时间同步的情况下,Cache-Control相比于expires是更好的选择。

4.3 Pragma

Pragma 是HTTP/1.0标准中定义的一个header属性,请求中包含Pragma的效果跟在头信息中定义Cache-Control: no-cache相同,但是HTTP的响应头没有明确定义这个属性,所以它不能拿来完全替代HTTP/1.1中定义的Cache-control头。通常定义Pragma以向后兼容基于HTTP/1.0的客户端。

注:以上三个响应头,优先级顺序为:Pragma>Cache-Control>Expires

协商缓存

4.4 ETag

ETag 值是一个字符串,其内容通常是数据的哈希值,每个数据都有一个单独的标志,只要这个文件发生了改变,这个标志就会发生变化。

服务器可以在响应中返回 ETag,然后浏览器会在后续的请求中携带上这个参数来确定缓存是否需要更新。如果 ETag 值相同,说明资源未更改,服务器会返回 304(Not Modified) 响应码,浏览器就知道本地缓存仍然是可以使用的。

4.5 Last-Modified

服务器可以通过配置这个响应头,来向浏览器发送一个数据上次被修改的时间标签,例如:Last-Modified:Wed, 24 Apr 2019 02:54:16 GMT

这样浏览器就知道了该数据最后被修改的时间,后续请求中,会和服务器进行时间的比较,如果服务器上的时间比本地时间要新,说明数据有更改,浏览器需要重新下载数据。

五.实例

禁用缓存: 启用协商缓存: 强缓存: 分析

  • 禁用缓存,就是设置响应头Cache-Control: no-store,max-age=0。浏览器收到响应头,就会指定制定禁止缓存的策略,下一次请求该资源,就会直接发送200请求。
  • 协商缓存,图片中Cache-Controll设置的实际是强缓存,但Pragma:no-cache是协商缓存,且Pragma优先级更高,因此这里执行的是协商缓存的策略,发送304请求,把本地资源的版本号、过期时间等信息拼装到请求头,来确定是否使用本地缓存。
  • 强缓存,这里干掉了Pragma响应头,浏览器就可以执行强缓存策略了,直接from memory cache。

六、用户操作行为与缓存的关系

  • 普通刷新:当按下F5或者点击刷新按钮来刷新页面的时候,浏览器将绕过本地缓存来发送请求到服务器, 此时, 协商缓存是有效的
  • 强制刷新:当按下ctrl+F5来刷新页面的时候, 浏览器将绕过各种缓存(本地缓存和协商缓存), 直接让服务器返回最新的资源
  • 回车或转向:当在地址栏上输入回车或者按下跳转按钮的时候, 所有缓存都生效