之前面试被问到浏览器的缓存机制,确实了解的不多,现在来记录一下最近知道的。
1、浏览器缓存的概念
简单来说,浏览器缓存就是把一个已经请求过的资源拷贝一份存储起来,当下次需要该资源时,浏览器会根据缓存机制决定直接使用缓存资源还是再次向服务器发送请求。
如图:
from memory cache 就代表着从缓存中获取的数据,并且大部分数据都是浏览器直接读取了缓存。
2、浏览器缓存的作用
我觉得作用可以从两方面来谈,一方面从用户的角度来说,加速了浏览,浏览器在用户磁盘上对请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览,提升了用户的体验
另一方面从网站的运营者来说,减少网络带宽消耗,可以有效的降低运营成本。 并且降低了服务器压力给网络资源设定有效期之后,用户可以重复使用本地的缓存,减少对源服务器的请求,间接降低服务器的压力。同时,搜索引擎的爬虫机器人也能根据过期机制降低爬取的频率,也能有效降低服务器的压力。
3、浏览器缓存的位置
from memory cache 表示浏览器从内存中读取的缓存,接下来我们看看还有哪些。
浏览器缓存位置分为四种,其优先级顺序如下:
a、Service Worker
b、Memory Cache
c、Disk Cache
d、Push Cache
当上述四个缓存位置中的缓存都没有命中时,则会向服务器发起请求。
Service Worker
Service Worker 是一个注册在指定源和路径下的事件驱动 worker。它采用 JavaScript 控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。
我们可以通过谷歌开发者工具中的 Application -> Service Workers 查看当前缓存的资源。
Memory Cache
Memory Cache 即内存中的缓存,其特点是容量小、读取高效、持续性短,会随着进程的释放而释放。
所以,在内存使用率低、缓存小尺寸资源时,会以 Memory Cache 为优先,否则使用 Disk Cache。
Disk Cache
Disk Cache 即磁盘中的缓存,其特点是容量大、读取缓慢、持续性长,任何资源都能存储到磁盘中。
所以,在内存使用率高、缓存大尺寸资源时,会以 Disk Cache 为优先。
Push Cache
Push Cache 是 HTTP 2.0 中的内容,其缓存时间也很短暂,只在会话(Session)中存在,一旦会话结束就被释放。
4、浏览器缓存的策略
浏览器每次在向服务器发起 HTTP 请求获得资源后,可能会根据不同情况将资源缓存起来。
浏览器缓存策略分为强制缓存和协商缓存,其是通过设置 HTTP Header 来实现的。
a、强制缓存
当浏览器发起 HTTP 请求时,会依次查找上述缓存位置中是否存在缓存资源并通过缓存标识字段 Expires 或 Cache-Control 来验证缓存资源是否过期。
Expires 是服务器端在响应请求时用来规定资源的失效时间。
Cache-Control 是服务器端在响应请求时用来规定资源是否需要被浏览器缓存以及缓存的有效时间等。
如图所示:
Cache-Control 主要取值如下:
Expires 是 HTTP 1.0 的字段,而 Cache-Control 是 HTTP 1.1 的字段,当 Expires 与 Cache-Control 同时存在时,Cache-Control 的优先级要高于 Expires。
若是命中缓存(即存在缓存资源并且缓存资源未过期),则浏览器响应 HTTP Status Code 200,并直接使用缓存资源作为返回结果,不需要发起 HTTP 请求;若是存在缓存资源但缓存资源已过期,则进入协商缓存。
b、协商缓存
与协商缓存相关的缓存标识字段是 Last-Modified 和 Etag。
Last-Modified 是服务器端在响应请求时用来说明资源的最后修改时间。与之对应的是 If-Modified-Since 字段,在协商缓存过程中,浏览器发送的 HTTP 请求中 Header 中会带上 If-Modified-Since 字段,值为缓存资源 Last-Modified 属性的值。
当服务器端接收到带有 If-Modified-Since 的请求时,则会将 If-Modified-Since 的值与被请求资源的最后修改时间做对比。如果相同,说明资源没有新的修改,则响应 HTTP Status Code 304,浏览器会继续使用缓存资源;如果最后修改时间比较新,则说明资源被修改过,则响应 HTTP Status Code 200,并返回最新的资源。
Etag 是服务器端在响应请求时用来说明资源在服务器端的唯一标识。与之对应的是 If-None-Match 字段,在协商缓存过程中,浏览器发送的 HTTP 请求中 Header 中会带上 If-None-Match 字段,值为该缓存资源 Etag 属性的值。
当服务器端接收到带有 If-None-Match 的请求时,则会将 If-None-Match 的值与被请求资源的唯一标识做对比。如果相同,说明资源没有新的修改,则响应 HTTP Status Code 304,浏览器会继续使用缓存资源;如果不同,则说明资源被修改过,则响应 HTTP Status Code 200,并返回最新的资源。
如图:
Last-Modified 是 HTTP 1.0 的字段,而 Etag 是 HTTP 1.1 的字段,当 Last-Modified 与 Etag 同时存在时,Etag 的优先级要高于 Last-Modified。
Etag 的出现主要是为了解决 Last-Modified 存在的问题:
Last-Modified 标注的最后修改只能精确到秒级,如果某些文件在 1 秒钟以内被修改多次的话,它将不能准确标注文件的最后修改时间;
如果本地打开缓存文件,即使没有对文件进行修改,但 Last-Modified 却改变了,导致文件没法使用缓存。
下面是我从网上找的一张流程图(自己画了画感觉不如人家的好。。 侵删)