# 前言
这篇文章我们主要来聊一聊浏览器的两种缓存机制:强缓存和协商缓存。
# 介绍
浏览器缓存分为强缓存与协商缓存两种方式:
- 强缓存是由
Header
里的Expires
字段实现的。 - 协商缓存有两种方式:
- 使用
Last-Modified
和If-Modified-Scene
实现。 - 使用
ETag
和If-None-Match
实现。
- 使用
# 强缓存
强缓存和协商缓存最大的一个区别在于:强缓存在验证请求是否存在缓存时,不需要向服务器发送请求。
当浏览器第一次向服务器发送请求时,服务器返回的返回头里如果设置了强缓存,浏览器会将请求返回内容与返回头一同存到浏览器缓存中。
当浏览器再次请求该改内容时,浏览器会先去缓存中寻找该请求,然后判断返回头里的缓存时间和当前客户端时间判断;如果在这时间之前的话,就直接重缓存中取得内容,F12
打开控制面板查看网络会发现请求显示 from cache
。
# 如何开启强缓存
在 Response Header
中使用 Expires
或 Cache-Control
即可。若二者同时存在,Cache-Control
优先级高于 Expires
。
# Expires
Expires
描述的是一个绝对时间,由服务器返回,用 GMT
格式的字符串表示,如:Expires:Thu, 31 Dec 2037 23:55:55 GMT
。
当使用 Expires
时,客户端将当前时间与 Expires
的值作比较,若当前时间晚于 Expires
时间,客户端将重新向服务器发起请求。
# Cache-Control
Cache-Control
是一个相对时间,在配置缓存的时候,以秒为单位,用数值表示,如:Cache-Control:max-age=315360000
。
当使用 Cache-Control
时,客户端会利用第一次请求时间与 Cache-control
值计算出一个过期时间,如何与客户端当前时间作比较,晚于当前时间,则重新向服务器发送请求。
# 强缓存的缺陷
由于客户端判断是否需要重新请求服务器的时间,是由客户端决定的,所以,若客户端时间与服务器时间不一致时(或用户主动更改了客户端时间),将导致缓存管理混乱,无法实现缓存功能。
# 协商缓存
由于强缓存的缺陷,后来提出了另一种缓存方式,即协商缓存。
协商缓存顾名思义,需要由服务器和客户端共同决定是否使用缓存数据。所以协商缓存不管是否使用缓存数据,都会向服务器发送一条请求。
服务器根据请求头中的 If-Modified-Scene
或 If-None-Match
来判断是否使用缓存内容。如果匹配成功,F12
打开控制台查看请求会显示 304
状态 Not Modified
。浏览器读到返回后去缓存中取得请求内容。如果匹配失败则直接返回新的内容。
【Last-Modified
、If-Modified-Since
】和【ETag
、If-None-Match
】一般都是同时启用,这是为了处理 Last-Modified
不可靠的情况。比如修改了客户端时间或是服务器上资源其实有变化,但是最后修改时间却没有变化的情况。
# Last-Modified 和 If-Modified-Scene
Last-Modified
是一个相对时间,以秒为单位,用数值表示,如:Cache-Control:max-age=315360000
。
浏览器发送请求时会在请求头中添加 If-Modified-Scene
,值为首次请求返回头中的 Last-Modified
。服务器在接收到请求后,会根据服务器上文件最新修改时间和请求头中的 If-Modified-Scene
作比较,确定是返回304 Not Modified 还是新的请求内容。
# ETag 和 If-None-Match
ETag
是一个服务器为该请求资源生成的一个唯一标志。首次请求时由服务器返回。
浏览器再次请求该资源时,会在请求头中添加 If-None-Match
。值为首次请求返回头中的 ETag
。服务器在接收到请求后,会根据服务器上文件的唯一标志和请求头中的 If-None-Match
作比较,确定是返回304 Not Modified还是新的请求内容。
# 协商缓存的缺陷
分布式系统下,每一台服务器为同一资源生成的唯一标志可能不同。如果请求是随机节点的话,也可能会出现缓存失效的情况。