浏览器缓存基本认识

作为一名前端开发,工作基本上就是天天和浏览器打交道。那缓存这块也是前端领域离不开的话题,深入理解浏览器缓存将更有利于我们在前端中优化。

浏览器缓存又分两种,分别是强制缓存协商缓存,两种缓存方式区别在于有无发起HTTP请求。

什么是浏览器缓存

浏览器向服务器获取资源(HTML页面、静态资源等)后,保存到浏览器的副本,当下一次请求同一个资源时,如果命中缓存规则,则直接使用浏览器的副本,否则重新向服务器获取新的资源。

强制缓存

当浏览器向服务器发起一个资源的HTTP请求后,会把当前资源的信息保存,再下一次继续加载该资源时,如果命中缓存规则就不会再向服务器发起HTTP请求,这种就称之为强制缓存。下面我们来看看如何能够命中强制缓存规则:

Expires

Expires是HTTP/1.0版本提出的,当浏览器向服务器获取某项资源时,Response Header会带有Expires字段返回,该字段内容存放的是过期的绝对时间,比如Expires:Mon, 29 Jan 2018 06:02:42 GMT,浏览器会保存当前资源和Response Header的内容,当下次再获取同一个资源时,浏览器会先把本地时间和Expires的时间做对比,如果当前时间还没到过期时间,则直接返回浏览器上次保存的资源,如果超过了该时间,则重新向服务器发起请求获取最新资源,并继续把当前资源和Response Header内容保存到本地。如果浏览器本地时间和服务器时间不一致的话,将直接影响缓存资源的判断。

Cache-Control

Cache-Control是HTTP/1.1版本提出的,当浏览器向服务器获取某项资源时,Response Header会带有Cache-Control字段返回,浏览器保存当前资源和Response Header的内容,当下次再获取同一个资源时,浏览器根据第一次的请求时间和Cache-Control设定的有效期,计算一个过期时间,如果请求时间还没到过期时间则命中缓存规则。Cache-Control字段存放内容相比Expires更加丰富,常见的有Cache-Control: max-age=31536000Cache-Control: no-cachemax-age是指缓存存储的最大周期,在这个时间范围内代表缓存有效,no-cache是值不使用任何缓存资源副本。

Cache-Control字段可设置的内容较多,除上述两个外,还有privatepublicno-store等等,具体可前往HTTP协议官方文档查阅

Cache-Control的优先级高于Expires,也就是说如果两者同时存在时,优先使用Cache-Control判断缓存规则。

协商缓存

当浏览器第一次向服务器获取一个资源时,浏览器会保存资源副本和Response Header到本地,下一次向服务器请求同个资源时,服务器会根据请求的Request Header中的某些字段做比较,如果符合缓存规则,服务器会向浏览器返回一个状态304 Not Modified表示资源相比较上一次请求时没有做修改,可以直接使用,这种就是协商缓存

If-None-Match/ETag

If-None-MatchETag是成对出现的,是存放资源的唯一标识符,浏览器向服务器发起请求时,会在Request Header带上If-None-Match,服务器接收到请求后,会和请求的资源的ETag做比对,如果两着的值为一样,那么服务器认为这一次的资源与上一次请求的资源是一致的,返回304 Not Modified给浏览器,通知浏览器可以直接使用缓存资源副本。如果If-None-MatchETag的值不一致,服务器会继续判断If-Modified-SinceLast-Modified

If-Modified-Since/Last-Modified

和上面的一样,If-Modified-SinceLast-Modified也是成对出现的,是存放上一次修改的时间,浏览器向服务器发起请求时,会在Request Header带上If-Modified-Since,服务器接收到请求后,会和请求的资源的Last-Modified做比对,如果两着的值为一样,那么服务器认为这一次的资源与上一次请求的资源是一致的,返回304 Not Modified给浏览器,通知浏览器可以直接使用缓存资源副本。

为什么协商缓存可以利用两种类型做校验,是因为If-Modified-Since/Last-Modified标注的时间只能精确到秒级,对于在1秒内发生多次修改的资源,则无法正确判断资源是否一致,而If-None-Match/ETag提供的标识符则是资源每次改动则发生变化,能够更好的判断资源是否发生改动。在实际开发中,会发生资源不做变更,但是修改的时间却发生变化了,这种情况下如果只用If-Modified-Since/Last-Modified做比对,则无法命中协商缓存,而If-None-Match/ETag能够解决此类问题。

If-None-Match/ETag的优先级高于If-Modified-Since/Last-Modified,也就是说服务器接收到请求后,会先比较前者,前者不一致的情况下再比较后者。