浏览器每次发起请求时,先在本地缓存中查找结果以及缓存标识,根据缓存标识来判断是否使用本地缓存。如果缓存有效,则使用本地缓存;否则,则向服务器发起请求并携带缓存标识。根据是否需向服务器发起HTTP请求,将缓存过程划分为两个部分:
强制缓存
和协商缓存
,强缓优先于协商缓存。
-
强缓存
,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时间内,执行比较缓存策略。 -
协商缓存
,让客户端与服务器之间能实现缓存文件是否更新的验证、提升缓存的复用率,将缓存信息中的Etag
和Last-Modified
。
通过请求发送给服务器,由服务器校验,返回304
状态码时,浏览器直接使用缓存。
HTTP缓存都是从第二次请求开始的:
- 第一次请求资源时,服务器返回资源,并在response header中回传资源的缓存策略;
- 第二次请求时,浏览器判断这些请求参数,击中强缓存就直接200,否则就把请求参数加到request header头中传给服务器,看是否击中协商缓存,击中则返回304,否则服务器会返回新的资源。这是缓存运作的一个整体流程图:
强缓存
浏览器在加载资源时,会先根据本地缓存资源的 header 中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。
这里的 header 中的信息指的是 expires
和 cache-control
。
Expires
该字段是 http1.0
时的规范,它的值为一个绝对时间的 GMT
格式的时间字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT
。这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱。
Cache-Control
Cache-Control
是 http1.1
时出现的 header 信息,主要是利用该字段的 max-age
值来进行判断,它是一个相对时间,例如 Cache-Control:max-age=3600
,代表着资源的有效期是 3600 秒。cache-control
除了该字段外,还有下面几个比较常用的设置值:
-
no-cache
:需要进行协商缓存,发送请求到服务器确认是否使用缓存。 -
no-store
:禁止使用缓存,每一次都要重新请求数据。 -
public
:可以被所有的用户缓存,包括终端用户和CDN
等中间代理服务器。 -
private
:只能被终端用户的浏览器缓存,不允许CDN
等中继缓存服务器对其缓存。 -
Cache-Control
与Expires
可以在服务端配置同时启用,同时启用的时候Cache-Control
优先级高。
协商缓存
当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据 header 中的部分信息来判断是否命中缓存。如果命中,则返回 304 ,告诉浏览器资源未更新,可使用本地的缓存。
这里的 header 中的信息指的是 Last-Modify/If-Modify-Since
和 ETag/If-None-Match
.
Last-Modify/If-Modify-Since
浏览器第一次请求一个资源的时候,服务器返回的 header
中会加上 Last-Modify
,Last-modify
是一个时间标识该资源的最后修改时间。
当浏览器再次请求该资源时,request 的请求头中会包含 If-Modify-Since,该值为缓存之前返回的 Last-Modify
。服务器收到 If-Modify-Since
后,根据资源的最后修改时间判断是否命中缓存。
如果命中缓存,则返回 304,并且不会返回资源内容,并且不会返回 Last-Modify
。
缺点:
短时间内资源发生了改变,Last-Modified
并不会发生变化。
周期性变化。如果这个资源在一个周期内修改回原来的样子了,我们认为是可以使用缓存的,但是 Last-Modified
可不这样认为,因此便有了 ETag
。
ETag/If-None-Match
与 Last-Modify/If-Modify-Since
不同的是,Etag/If-None-Match
返回的是一个校验码。ETag
可以保证每一个资源是唯一的,资源变化都会导致 ETag
变化。服务器根据浏览器上送的 If-None-Match 值来判断是否命中缓存。
与 Last-Modified
不一样的是,当服务器返回 304 Not Modified
的响应时,由于 ETag
重新生成过,response header
中还会把这个 ETag
返回,即使这个ETag
跟之前的没有变化。
网友评论