缓存的机制(规则)
浏览器在加载资源时,根据请求头的Expires 和 Cache-control 判断是否命中强缓存,是则直接从缓存读取资源,不会发请求到服务器。
如果没有命中强缓存,浏览器一定会发送一个请求到服务器,通过 Last-Modified 和 Etag 验证资源是否命中协商缓存,如果命中,服务器会将这个请求返回,但是不会返回这个资源的数据,依然是从缓存中读取资源。
如果前面两者都没有命中,直接从服务器加载资源。
1. 强缓存
强缓存的意思就是不向服务器发起请求的缓存,也就是本地强制缓存。浏览器想要获取特定数据的时候,首先会检查一下本地的缓存是否存在该数据,如果存在,就直接在本地获取了,如果不存在,就向服务器所要该数据。
详细请求过程如下动画所示:
那么问题来了,如果我们想使用强缓存,那怎么判断缓存数据什么时候失效呢?
当浏览器向服务器请求数据的时候,服务器会将数据和缓存的规则返回,在响应头的 header 中,有两个字段 Expires和Cache-Control。
如果 Expire 和 Cache-control 两者同时出现,则以 Cache-control 为主
2. 协商缓存
浏览器第一次请求数据时,服务器会将缓存标识与数据一起返回给客户端,客户端将二者备份至缓存数据库中。
再次请求数据时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识进行判断,判断成功后,返回304状态码,通知客户端比较成功,可以使用缓存数据。
注意:Etag 优先级高于Last-modifed
怎么来识别协商缓存的?
主要通过报文头部 header 中的Last-Modified,If-Modified-Since 以及ETag、If-None-Match 字段来进行识别。
总结:
缓存这东西,第一次必须获取到资源后,然后根据返回的信息来告诉如何缓存资源,可能采用的是强缓存,也可能告诉客户端浏览器是协商缓存,这都需要根据响应的header内容来决定的。下面用两幅图来描述浏览器的缓存是怎么玩的,让大家有个大概的认知。
浏览器第一次请求时:
浏览器后续在进行请求时:
强缓存与协商缓存的区别,可以用下表来进行描述:
注意1:如果cache-control与expires同时存在的话,cache-control的优先级高于expires
注意2:Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
根据查到的资料显示,缓存头的优先级是这样的:
Pragma > Cache-Control > Expires > Etag > Last-Modified