前言
为什么在网络相同的情况下,第二次打开相同的网页会比第一次快很多呢?因为浏览器已经把一些资源给缓存下来了,接下来我们来解析一下浏览器缓存。
开始
在我们打开一个网页的时候,会加载很多资源,例如图片、音频、视频、js文件、css文件等,这些资源的加载会导致我们的网页渲染的速度变慢,因为浏览器的渲染进程是单线程工作的,只有一个任务完成后才会执行另一个任务。所以如何加快网页渲染的速度呢,这时候就需要用到浏览器缓存机制了。
强制缓存
强制缓存有两种,一种是Expires,另一种是Cache-Control,首先我们来介绍Expires
Expires
Expires是Http1.0的时候提出来的,具体使用方式如下
Expires: Sun, 21 Mar 2021 08:22:34 GMT
这表示该资源在2021年3月21号8点22分34秒之前不会过期
浏览器的网络进程在解析服务器返回来的响应头时,如果携带改字段,那么浏览器就会把改资源缓存下来,并且在2021年3月22号8点22分34秒之前获取该资源的时候,都不会发起真正的网络请求,而是会从内存中去获取。 但是这种缓存方式存在一个重大的缺陷,导致在http1.1版本的时候提出来了另一个强制缓存的方式。
当服务器时间和用户的本地时间不一致的时候,就可能会导致该缓存失效,比如说服务器返回来的是Expires: Sun, 21 Mar 2021 08:22:34 GMT,表明2021年3月21号8点22分34秒之前不会过期,但是用户的本地时间却是2021年3月22号,这时候就不会缓存命中,每次获取该资源的时候都会去发起真正的请求。
Cache-Control
Cache-Control是在Http1.1版本中提出来的强制缓存的另一种方式
Cache-Control: max-age=3600
这表示该资源在当前时间的3600秒内不会过期
也是和Expires字段一样,当网络进程解析服务器返回来的响应头时,如果携带该字段,那么浏览器就会缓存该资源,并且在当前时间的3600秒之内重新获取该资源会直接从缓存中获取数据,而不会发起真正的请求。 如果我们再一次请求该资源,我们来看看浏览器的network面板
重点来看这个Status Code字段,后面写着 from memory cache 这表明我们是从缓存中直接读取的,我们再来看看从缓存中读取的时间。
Cache-Control属性中还有很多字段,比如说:
public: 表示该资源不论是客户端还是代理服务器都能缓存
private: 表示该资源只能客户端缓存
no-cache:表示跳过当前强制缓存,进入协商缓存阶段
no-store:表示不需要缓存
值得注意的是当服务器返回来的响应头中同时携带Expires和Cache-Control时,浏览器会选择使用Cache-Control
协商缓存
协商缓存是浏览器缓存的第二步,当强制缓存失效的时候就会进入协商缓存阶段。协商缓存有两种形式,一种是 Last-Modified 和 ETag,首先来讲Last-Modified
Last-Modified
见名知意,Last-Modified表示该资源的最后修改时间,具体格式如下:
Last-Modified: Wed, 17 Mar 2021 08:20:57 GMT
这表示该资源的最后修改日期是2021年3月17号8点20分57秒
当服务器的响应头中出现该字段,浏览器会把该属性的值和该资源保存下来,当下一次请求该资源的时候,浏览器会在请求头中加入
If-Modified-Since: Wed, 17 Mar 2021 08:20:57 GMT
当服务器解析到请求头中携带该字段的时候,会把这个值和服务器中的该资源的最后修改时间做对比,如果两个值相同那么服务器就会直接返回304状态码给浏览器,304表示Not Modified,浏览器就会直接拿缓存中的资源。
当两个值不相同的时候,服务器就会返回最新的资源并且在响应头中的Last-Modified的值就会变更成最新的资源修改时间。
缺陷
Last-Modified也是存在缺陷的,因为该属性只精确到了秒。当服务器中的资源在一秒钟之内改变了多次,那么这时候并没有体现出了修改,这时候就会造成服务器的资源和浏览器缓存的资源的不匹配的问题。
ETag
Etag是协商缓存的另一种方式,它表示的是资源的唯一标识,当资源改变的时候,标识也会随着改变,具体格式如下:
ETag: "6051bbe9-1afd1"
表示该资源的唯一标识是--"6051bbe9-1afd1"
也是和Last-Modified一样,当服务器的响应头中出现ETag字段的时候,浏览器就会把该资源和ETag后面的值保存下来,当再次请求的时候就会在请求头中加入
If-None-Match: "6051bbe9-1afd1"
当服务器解析请求头的时候,就会把该唯一标识符和在服务器中的唯一标识符做对比,相同则返回304,若不相同则会把最新的资源和最新的标识符传递给浏览器。
注意的是,当协商缓存的两种方式都存在的时候,服务器优先选择 ETag
总结
当我们请求一个资源的时候,浏览器会首先判断强制缓存,如果强制缓存命中,则会直接从缓存中读取。 若强制缓存失效,则会进入协商缓存阶段,若协商缓存命中,则直接使用缓存中的资源。 否则会发起真正的http请求来获取资源。(这是一些个人看法,感谢您的阅读,若有不对请指教!^.^)