简单来讲,浏览器缓存就是把一个已经请求过的资源拷贝一份存储起来,当下次须要该资源时,浏览器会根据缓存机制决定直接使用缓存资源仍是再次向服务器发送请求。前端
以下图所示是我在第二次打开某个网页时的资源请求图,能够看出里面大部分资源是从浏览器直接读取了缓存。浏览器
那么浏览器缓存究竟有什么做用呢?缓存
浏览器缓存最主要的做用是减小网络传输的损耗以及下降服务器压力。服务器
接下来我将经过如下几个部分来探讨浏览器缓存机制:网络
浏览器缓存位置分为四种,其优先级顺序以下:工具
当上述四个缓存位置中的缓存都没有命中时,则会向服务器发起请求。学习
Service Worker 是一个注册在指定源和路径下的事件驱动 worker。它采用 JavaScript 控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。网站
咱们能够经过谷歌开发者工具中的 Application -> Service Workers 查看当前缓存的资源。3d
Memory Cache 即内存中的缓存,其特色是容量小、读取高效、持续性短,会随着进程的释放而释放。cdn
因此,在内存使用率低、缓存小尺寸资源时,会以 Memory Cache 为优先,不然使用 Disk Cache。
Disk Cache 即磁盘中的缓存,其特色是容量大、读取缓慢、持续性长,任何资源都能存储到磁盘中。
因此,在内存使用率高、缓存大尺寸资源时,会以 Disk Cache 为优先。
Push Cache 是 HTTP 2.0 中的内容,其缓存时间也很短暂,只在会话(Session)中存在,一旦会话结束就被释放。
浏览器每次在向服务器发起 HTTP 请求得到资源后,可能会根据不一样状况(多是代码控制如 Service Worker、Push Cache,也多是根据 HTTP Header 的缓存标识字段)将资源缓存起来。
浏览器缓存策略分为强制缓存和协商缓存,其是经过设置 HTTP Header 来实现的。
当浏览器发起 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 请求;如果存在缓存资源但缓存资源已过时,则进入协商缓存。
与协商缓存相关的缓存标识字段是 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 存在的问题:
下面用一张流程图来完整说明当浏览器发起 HTTP 请求时缓存机制的过程:
公众号不定时分享我的在前端方面的学习经验,欢迎关注。