网络方面的缓存分为三块:DNS缓存、HTTP缓存、CDN缓存,也有人把这里的 HTTP 缓存称为浏览器缓存。
还有本地的就是:浏览器的本地存储和离线存储,更快提高首屏加载速度,让页面飞起
# 1、DNS缓存
进入页面的时候会进行DNS查询,找到域名对应的服务器的IP地址,再发送请求
# 2、HTTP缓存
就是将http请求获取的页面资源存储在本地,之后再加载直接从缓存中获取而不用请求服务器,从而响应更快。先看图:
# 2-1、强缓存
- 强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程,强制缓存的情况主要有三种
1.不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求(跟第一次发起请求一致),如下图:
2.存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存(暂不分析),如下图
3.存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果,如下图
控制强制缓存的字段分别是Expires和Cache-Control,其中Cache-Control优先级比Expires高。
# Expires:用来指定资源到期绝对时间,服务器响应时,添加在响应头中。
expires: Wed, 22 Nov 2021 08:41:00 GMT
注意:如果服务器和浏览器端时间不一致的话可能导致失败。比如现在时间是8月1,expires过期时间是8月2,客户端把电脑时间改成了8月3,那就用不了这个缓存
# Cache-Control:指定资源过期时间秒,如下,表示在这个请求正确返回后的300秒内,资源可以使用,否则过期。添加在响应头中。
cache-control:max-age=300
Expires 和 Cache-Control 的区别
1、Expires 是HTTP/1.0中的,Cache-Control 是HTTP/1.1中的;
2、两者同时存在的话 Cache-Control 优先级高于 Expires;
强缓存的缺点:
就是缓存过期之后,不管资源有没有变化,都会重新发起请求,重新获取资源
而实际情况是在资源文件没有更新的情况下,即使过期了也不重新获取资源,继续使用旧资源,
所以协商缓存它来了,在强缓存过期的情况下,再走协商缓存的流程,判断文件有没有更新。
# 2-2、协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:
1.协商缓存生效,返回304,如下
2.协商缓存失效,返回200和请求结果结果,如下
控制协商缓存的字段分别有:Last-Modified / If-Modified-Since和Etag / If-None-Match,其中Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高。
# 2-2-1、Last-Modified/If-Modified-Since
第一次请求资源时,服务器除了会返回给浏览器上面说的过期时间,还会在响应头添加 Last-Modified 字段,告诉浏览器该资源的最后修改时间
last-modified: Fri, 27 Oct 2021 08:35:57 GMT
然后浏览器再次请求的时候就把这个时间再通过另一个字段 If-Modified-Since 添加到请求头,发送给服务器
if-modified-since: Fri, 27 Oct 2021 08:35:57 GMT
服务器再把这两个字段的时间对比,如果是一样的,就说明文件没有被更新过,就返回状态码304和空响应体给浏览器,浏览器直接拿过期了的资源继续使用即可;如果对比不一样说明资源有更新,就返回状态码200和新的资源。
所以说 Last-Modified/If-Modified-Since 是成对的,是为了对比文件修改时间
Last-Modified/If-Modified-Since的缺点:
1、如果本地打开了缓存文件,即使没有对文件进行修改,但还是会造成Last-Modified被修改,服务器端不能命中缓存导致发送相同资源
2、因为Last-Modified只能以秒计时,如果在不可感知的时间内修改了文件,服务器端会认为还是命中了,无法返回正确的资源
3、如果资源有周期性变化,如资源修改后,在一个周期内又改回了原来的样子,我们认为这个周期前的缓存是可以使用的,但是Last-Modified不这样认为
# 2-2-2、ETag/If-None-Match
第一次请求资源时,服务器除了会在响应头上返回Expires、Cache-Control、Last-Modified,还在返回Etag字段,表示当前资源文件的一个唯一标识。
这个标识符由服务器基于文件内容编码生成,能精准感知文件的变化,只要文件内容不同,ETag就会重新生成
etag: W/"132489-1627839023000"
然后浏览器再次请求的时候就把这个文件标识 再通过另一个字段 If-None-Match,发送给服务器
if-none-match: W/"132489-1627839023000"
服务器再把这两个字段对比,如果发现是一样的,就说明文件没有被更新过,就返回状态码304和空响应体给浏览器,浏览器直接拿过期了的资源继续使用;
如果对比不一样说明资源有更新,就返回状态码200和新的资源。
Last-Modified 和 ETag 的区别:
1、Etag 感知文件精准度要高于 Last-Modified
2、同时使用时,服务器校验优先级 Etag/If-None-Match
3、Last-Modified 性能上要优于 Etag,因为 Etag 生成过程中需要服务器付出额外开销,会影响服务器端的性能,所以它并不能完全替代 Last-Modified,只能作为补充和强化
# 强缓存与协商缓存的区别:
- 优先查找强缓存,没有命中再查找协商缓存
- 强缓存不发请求到服务器,所以有时候资源更新了浏览器还不知道,但是协商缓存会发请求到服务器,资源是否有更新,服务器肯定知道
- 目前项目大多数使用缓存的方案
1、协商缓存一般存储:HTML
2、强缓存一般存储:css, image, js,文件名带上 hash