最近做项目遇到了浏览器缓存导致页面数据没有更新。以及页面样式未更新的情况。这是因为浏览器缓存导致的。所以来总结一下浏览器缓存的知识。
良好的缓存策略可以降低资源的重复加载提高网页的整体加载速度。针对现在的vue、react的单页面应用,在做性能优化这块,缓存策略也是必须考虑的。
缓存带来的好处
- 减少冗余的数据传输,节省带宽。
- 减轻服务器的请求负担,有缓存就可以少向服务器发送请求,尤其是对于一些访问量大的网站这点还是很重要的。
- 资源从缓存中读取,无需向服务器发送请求再等待返回,加快了客户端的访问速度。
缓存带来的问题
如果项目更新了,但是用户访问时浏览器读取的是缓存资源,那么用户就获取不到最新的页面,影响用户使用。
缓存分类
web缓存分为很多种,比如数据库缓存、代理服务器缓存、CDN缓存,以及浏览器缓存。 浏览器通过代理服务器向源服务器发起请求的原理如图。
浏览器缓存主要指http缓存,其机制是根据http报文的缓存标识进行相应操作。
http缓存存机制
主要是根据http报文的缓存标识进行响应操作。
http状态码
在讨论浏览器缓存之前,我们先看看网页相关的http状态码,打开控制台,在Network下捕捉请求,注意Status和Size栏,会看到200 from disk cache,200数值大小。
| status | size | 解释 |
|---|---|---|
| 200 | memory cache | 状态码是灰色的,从内存中读取之前已经加载过的资源,不请求服务器,页面关闭时,资源就会被内存释放,再次打开相同页面不会出现此类情况,在同一页面刷新才会出现。一般脚本、字体、图片会存在内存当中 |
| 200 | disk cache | 状态码是灰色的,从磁盘中读取之前已经加载过的资源,不请求服务器,页面关闭不会被释放,这部分资源存在电脑磁盘里,只有用户手动清除浏览器缓存的时候才会释放 |
| 200 | 数值大小 | 从服务器下载最新资源,数值是从服务器获取的全部资源大小 |
| 304 | 数值大小 | 访问服务器,发现资源没有更新,使用本地资源。数值是与服务器通信报文的大小,并不是资源本身的大小。 |
浏览器三级缓存原理
- 内存缓存:读取速度最快
- 本地缓存:读取速度快
- 网络缓存:读取速度最慢
缓存流程
- 先查找内存,如果内存中存在,从内存中加载;
- 如果内存中未查找到,选择硬盘获取,如果硬盘中有,从硬盘中加载;
- 如果硬盘中未查找到,那就进行网络请求,加载到的资源缓存到硬盘和内存;
缓存策略
通常浏览器的缓存策略分为两种:
- 强缓存
- 协商缓存
强缓存:Expires&Cache-Control
强制缓存就是,用户第一次访问页面之后,浏览器将数据存在缓存中,在过期时间之内,都不会再请求服务器。是否使用强制缓存在于资源是否过期,该过期时间从第一次请求的服务器响应头中获取。如果在过期时间内,从缓存中读取,如果超出过期时间,则使用协商缓存。
控制强制缓存的字段分别是Expires和Cache-Control,其中Cache-Control优先级比Expires高。
Cache-Control头
HTTP/1.1定义的 Cache-Control 头用来区分对缓存机制的支持情况, 请求头和响应头都支持这个属性。通过它提供的不同的值来定义缓存策略。
在请求头中使用时,可选值有:
| 字段 | 说明 |
|---|---|
| no-store | 没有缓存:缓存中不得存储任何关于客户端请求和服务端响应的内容。每次由客户端发起的请求都会下载完整的响应内容。 |
| no-cache | 缓存但重新验证:如下头部定义,此方式下,每次有请求发出时,缓存会将此请求发到服务器(译者注:该请求应该会带有与本地缓存相关的验证字段),服务器端会验证请求中所描述的缓存是否过期,若未过期(注:实际就是返回304),则缓存才使用本地缓存副本。 |
| private | 私有:响应是专用于某单个用户的,中间人不能缓存此响应,该响应只能应用于浏览器私有缓存中。 |
| public | 响应可以被任何中间人(译者注:比如中间代理、CDN等)缓存 |
| max-age | 过期机制中,最重要的指令是 "max-age=",表示资源能够被缓存(保持新鲜)的最大时间。 |
| must-revalidate | 验证方式:意味着缓存在考虑使用一个陈旧的资源时,必须先验证它的状态,已过期的缓存将不被使用。 |
协商缓存:Last-Modified&Etag
协商缓存,从字面意思,就是要协商,是浏览器和服务器协商,那么浏览器每次都要和服务器通信。在第一次请求服务器时,服务器会返回资源,并且返回一个资源的缓存标识,一起存到浏览器的缓存数据库。当第二次请求资源时,浏览器会首先将缓存标识发送给服务器,服务器拿到标识后判断标识是否匹配,如果不匹配,表示资源有更新,服务器会将新数据和新的缓存标识一起返回到浏览器;如果缓存标识匹配,表示资源没有更新,并且返回 304 状态码,浏览器就读取本地缓存服务器中的数据。
与协商缓存有关的字段是Last-Modified/IF-Modified-Since、Etag/IF-None-Match。
Etag
作为缓存的一种强校验器,如果资源请求的响应头里含有ETag, 客户端可以在后续的请求的头中带上 If-None-Match 头来验证缓存。
Last-Modified
Last-Modified作为一种弱校验器,说它弱是因为它只能精确到一秒。如果响应头里含有这个信息,客户端可以在后续的请求中带上 If-Modified-Since 来验证缓存。
vary响应
Vary HTTP 响应头决定了对于后续的请求头,如何判断是请求一个新的资源还是使用缓存的文件。
当缓存服务器收到一个请求,只有当前的请求和原始(缓存)的请求头跟缓存的响应头里的Vary都匹配,才能使用缓存的响应。
参考链接: