浏览器缓存策略

ObjectKaz Lv4

介绍

为什么需要浏览器缓存

当你第一次访问页面的时候,浏览器会自动下载所有与这个页面有关的资源,例如 CSS、网页字体、JavaScript脚本。

但是,在很短一段时间内,当你第二次访问网页时,这些资源往往是不变的。如果这个时候仍然再加载这些 CSS、网页字体、JavaScript脚本,那么,不但增加了服务器的负担,也增加了请求的时间,这对双方都是十分不利的。

如果这个时候能够把一些很少变化的资源缓存起来,那么下次加载页面时,直接从硬盘读取数据,而不从服务器加载,那么既减少了服务器的负担,也减少了网页的加载时间。

总的来说,使用浏览器缓存,可以:

  • 对于服务器:缓解服务器压力,减小服务器带宽
  • 对于客户:减少内容加载时间,节省流量

在开发者工具中查看缓存情况

这里以京东首页为例。下图是第二次加载网页时,浏览器开发者工具的例子:

可以发现,有不少的资源被标注为了 disk cache 或 内存缓存。这些被标注的资源都是从本地加载的,而不是通过网络加载的。

在网络面板上面,有一个 停用缓存 的按钮。点击它以后可以禁用浏览器的缓存,从而观察网页首次加载的情况。

什么时候缓存

这一部分,我们就要探讨:什么时候使用缓存,什么时候不使用缓存。

浏览器提供了下面的两种策略来解决这个问题:

  • 强缓存策略
  • 协商缓存策略

强缓存策略

强缓存是说,如果本地已经有某个资源的缓存,而且没有过期,那么就直接使用本地的缓存,否则从服务器上加载数据。

我们结合流程图来理解强缓存:

graph LR
START(开始)-->TRYLOAD[请求某个资源]-->CHECK{缓存是否存在且未过期}--是-->USECACHE[使用缓存]-->END(结束)
CHECK--否-->LOADRESOURCES[发起网络请求]-->END(结束)

了解了整个流程之后,我们就来看看它是怎么实现的。

Expires

在 HTTP 1.0 中,强缓存是通过 Expires Header 控制的。

1
Expires: Fri, 24 Oct 2031 18:22:16 GMT

但是,这个字段功能十分局限,只能指定一个绝对时间。

  • 首先,这给出的是一个绝对时间。这意味着如果用户修改了电脑时间,那么这个设置可能就失效了。
  • 其次,它对于时间的格式有着苛刻的要求,如果传入了一个错误的时间字符串,这个字段就会失效。

Cache-Control

于是,在HTTP 1.1 中,新增了一个 Cache-Control Header 字段。

接下来对一些常用的值进行讲解。

缓存时间

  • max-age=<seconds>:通常用于设置一个缓存的最大有效时间,单位为秒
  • s-maxage: 通常用于客户端和服务器中间的代理服务器的有效时间,如果指定了这个,那么对于代理服务器来说,max-age 会被忽略。

缓存的作用域

  • public:资源可以被客户端和客户端和服务器中间的代理服务器缓存。
  • private:默认。资源只有客户端可以缓存。

缓存策略

  • must-revalidate:如果超过了 max-age 的时间,浏览器必须重新请求验证资源。
  • no-cache:无论本地副本是否过期,使用之前必须发送请求来验证资源是否过期。
  • no-store: 禁止使用缓存,资源每次都从网络中加载。

具体的属性信息,可以参考:MDN

常用的一些值:

  1. 禁止缓存:Cache-Control: no-store
  2. 设置缓存时间为1小时:Cache-Control:public, max-age=3600

Cache-ControlExpires 如果同时指定了,那么 Cache-Control 会覆盖 Expires

强缓存有一个缺点:一旦指定了这两个字段,浏览器在一定时间内就不会再次从服务器加载数据了。一旦这个时候数据发生了更新,用户如果没有清理浏览器缓存,拿到的仍然是旧的数据。

协商缓存策略

当强缓存失效后,浏览器携带缓存标识向服务器发起请求,浏览器根据响应结果来判断是否继续使用缓存。

  • 如果响应304,则表示资源没有发生改变,浏览器继续使用缓存。
  • 如果响应200,则表示缓存失效,服务器返回新的资源。

尽管浏览器仍然请求了服务器,但是如果资源没有发生更改,服务器无需返回新的资源,从而减少了网络传输的体积。

同样的,我们结合流程图来解释整个流程:

graph LR
START(开始)-->TRYLOAD[请求某个资源]-->CHECK{缓存是否存在且未过期}--是-->USECACHE[使用缓存]-->END(结束)
CHECK--否-->REQUEST[携带标识发起网络请求]-->ISEXPIRED{服务器是否返回403}--是-->USECACHE
ISEXPIRED--否-->LOADRES[加载新的资源]-->END

协商缓存通常是结合一对请求响应头来实现的:

  • Last-Modified 和 If-Modified-Since
  • Etag 和 If-None-Match

接下来我们来分别讨论这两对响应头。

Last-Modified 和 If-Modified-Since

在第一次加载资源的时候,服务器会返回一个 Last-Modified 字段:

1
Last-Modified: Fri, 10 May 2019 03:38:54 GMT

浏览器得到响应后,会将数据和这个信息一起存储。

当缓存过期之后,浏览器便会在请求头上 增加一个名为 If-Modified-Since 、值为 Last-Modified 字段。服务器通过比对 Last-ModifiedIf-Modified-Since,来判断缓存是否过期。

但是这种方法有一些问题:

  1. 这个字段的最小时间单位为秒,这意味着资源更新的速度比秒级还小,这个字段就没办法使用了。
  2. 如果文件是动态生成的,那么这个时间也是实时更新的,哪怕文件内容没有变,这个字段也没法用了。

Etag 和 If-None-Match

这个整体流程和上一小节是一致的,其中,Etag对应 Last-ModifiedIf-Modified-Since对应If-None-Match

只不过Etag 使用文件的特殊标识(例如修改时间的 hash或文件值的hash)来代替时间。这样就规避了上面方法的两个问题。

在哪里存的

我们刚刚探讨了在浏览器中,什么时候使用缓存,这一部分,我们探讨浏览器缓存的存储位置。

在浏览器中,缓存保存在下面四个位置:

  • Service Worker
  • Memory Cache
  • Disk Cache
  • Push Cache

Service Worker

PWA(Progressive Web Apps,渐进式 Web 应用) 是一项新技术,它综合运用各种Web API,使得Web App 能够拥有像原生应用一样的体验。

其中 Service Worker 是实现PWA的一个重要技术。Service Worker 是运行在浏览器的一个独立的线程,相当于界面和Web服务器之间的一个代理,通过它,我们可以自由地控制:缓存什么文件、如何匹配缓存、如何读取缓存。它可以让网页中的资源进行离线缓存,使得在网络较差或者离线的时候,也能够对网页进行正常的操作,从而提高用户体验。

Service Worker 和 PWA 的具体内容会来未来的某一篇文章中提到。

Memory Cache

相比于磁盘,内存的速度是相当快的,所以如果网页没有关闭,而只是刷新一下,或者网页内的跳转,那么大部分内容会被载入 Memory Cache。

但是 Memory 一般间隔很短,一旦网页关闭了,对应的浏览器进程也就关闭了,缓存便被释放了。

Disk Cache

顾名思义,Disk Cache是存储在硬盘的。相比于Memory Cache,Disk Cache可以较长时间来保存缓存。但是,毕竟硬盘的速度比内存要慢一些,所以其访问速度比Memory Cache慢一些。

Push Cache

Push Cache是 HTTP/2 中的内容。

如果上面的三种缓存都没有命中,那么就会采用这种缓存。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂,在Chrome浏览器中只有5分钟左右,同时它也并非严格执行HTTP头中的缓存指令。

加载顺序

当一个资源进行加载时,浏览器会按照下面的策略来按顺序来加载缓存,这称为 三级缓存原理

  • 查找内存缓存,如果存在,那么从内存中加载
  • 如果内存缓存不存在,那么去磁盘中查找,找到便从磁盘中加载。
  • 否则,进行网络请求,并将请求后符合条件的资源存入内存和磁盘中

参考资源

  1. 一文读懂前端缓存 作者:小蘑菇哥哥 链接:https://juejin.cn/post/6844903747357769742
  2. 前端浏览器缓存知识梳理 作者:黑色的枫 链接:https://juejin.cn/post/6947936223126093861
  3. web性能优化之:no-cache与must-revalidate深入探究 作者:程序猿小卡_casper 链接:https://segmentfault.com/a/1190000007317481
  • 标题: 浏览器缓存策略
  • 作者: ObjectKaz
  • 创建于: 2021-11-04 13:23:47
  • 更新于: 2021-11-11 03:47:40
  • 链接: https://www.objectkaz.cn/e1646e2e9feb.html
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。