缓存分类
在一个C/S结构中,最基本的缓存分为两种:
- 客户端缓存
-
客户端缓存
当你将一个url粘贴进地址栏中 浏览器怎吗判断缓存?
此时客户端(浏览器)回去看一个缓存中是否有缓存?
查看缓存
先看一下服务器的缓存指令
服务器会在响应头添加
Cache-Control: max-age=3600
ETag: W/"121-171ca289ebf"
Date: Thu, 30 Apr 2020 12:39:56 GMT
Last-Modified: Thu, 30 Apr 2020 08:16:31 GMT
这个响应头表达了下面的信息:
Cache-Control: max-age=3600,我希望你把这个资源缓存起来,缓存时间是3600秒(1小时)
- ETag: W/“121-171ca289ebf”,这个资源的编号是W/“121-171ca289ebf”
- Date: Thu, 30 Apr 2020 12:39:56 GMT,我给你响应这个资源的服务器时间是格林威治时间2020-04-30 12:39:56
- Last-Modified: Thu, 30 Apr 2020 08:16:31 GMT,这个资源的上一次修改时间是格林威治时间2020-04-30 08:16:31
浏览器会
- 浏览器把这次请求得到的响应体缓存到本地文件中
- 浏览器标记这次请求的请求方法和请求路径
- 浏览器标记这次缓存的时间是3600秒
- 浏览器记录服务器的响应时间是格林威治时间2020-04-30 12:39:56
- 浏览器记录服务器给予的资源编号W/“121-171ca289ebf”
- 浏览器记录资源的上一次修改时间是格林威治时间2020-04-30 08:16:31
客户端查找缓存
请求方法+请求路径
要验证是否有匹配的缓存非常简单,只需要验证当前的请求方法GET和当前的请求路径/index.js是否有对应的缓存存在即可
如果没有缓存直接请求服务器
找到缓存进行啦吗?可不是还要判断缓存是否有效
Vary
有的时候,是否有缓存,不仅仅是判断请求方法和请求路径是否匹配,可能还要判断头部信息是否匹配。
此时,就可以使用Vary字段来指定要区分的消息头
比如,当使用GET /personal.html请求服务器时,请求头中cookie的值不一样,得到的页面也不一样
如果还按照之前的做法,仅仅匹配请求方法和请求路径,如果cookie变动,你可能得到的仍然是之前的页面。
缓存的有效与无效
缓存时间
Cache-Control
Cache-Control是服务器向客户端响应的一个消息头,它提供了一个max-age用于指定缓存时间。
实际上,Cache-Control还可以设置下面一个或多个值:
- public:指示服务器资源是公开的。比如有一个页面资源,所有人看到的都是一样的。这个值对于浏览器而言没有什么意义,但可能在某些场景可能有用。本着「我告知,你随意」的原则,http协议中很多时候都是客户端或服务器告诉另一端详细的信息,至于另一端用不用,完全看它自己。
- private:指示服务器资源是私有的。比如有一个页面资源,每个用户看到的都不一样。这个值对于浏览器而言没有什么意义,但可能在某些场景可能有用。本着「我告知,你随意」的原则,http协议中很多时候都是客户端或服务器告诉另一端详细的信息,至于另一端用不用,完全看它自己。
- no-cache:告知客户端,你可以缓存这个资源,但是不要直接使用它。当你缓存之后,后续的每一次请求都需要附带缓存指令,让服务器告诉你这个资源有没有过期。见:「来自客户端的缓存指令 - 缓存无效」
- no-store:告知客户端,不要对这个资源做任何的缓存,之后的每一次请求都按照正常的普通请求进行。若设置了这个值,浏览器将不会对该资源做出任何的缓存处理。
- max-age:不再赘述
比如,Cache-Control: public, max-age=3600表示这是一个公开资源,请缓存1个小时
Expire
在http1.0版本中,是通过Expire响应头来指定过期时间点的,例如:
Expire: Thu, 30 Apr 2020 23:38:38 GMT
到了http1.1版本,已更改为通过Cache-Control的max-age来记录了。
缓存有效期
浏览器会按照服务器响应头的要求,自动记录缓存到本地文件,并设置各种相关信息
在这些信息中,有效期尤为关键,它决定了这个缓存可以使用多久
浏览器会根据服务器不同的响应情况,设置不同的有效期
具体的有效期设置,按照下面的流程进行:
例如,当max-age设置为0时,缓存立即过期
虽然立即过期,但缓存仍然被记录下来,后续的请求通过缓存指令发送到服务器,来确认资源是否被更改。
因此,Cache-Control: max-age=0类似于Cache-Control: no-cache
缓存有效
当浏览器发现缓存有效时,完全不会请求服务器,直接使用缓存即可得到结果
此时,如果你断开网络,会发现资源仍然可用
这种情况会极大的降低服务器压力,但当服务器更改了资源后,浏览器是不知道的,只要缓存有效,它就会直接使用缓存
服务器更改了资源后,浏览器是不知道的,只要缓存有效,它就会直接使用缓存
示例:vue程序怎吗解决这个问题
vue 打包后的文件
但是inex.html的文件名是不变的
那我们可以将index.html 的缓存时间设置成立即过期,每次访问vue的页面,让浏览器访问一下服务器看文件是否改动,没改动让浏览器从缓存中读取,有改动个浏览器发送新的响应。因为你每次改动vue文件,再次打包后文件名是不一样的,只是index.html的特殊性没有将其修改文件名,而且其他其他文件的引入连接写在index.html中, 其他文件就可以设置一个长期缓存时间,
缓存无效
当缓存过期,浏览器向服务器发出了一个带缓存的请求
所谓带缓存的请求,无非就是加入了以下的请求头:
If-Modified-Since: Thu, 30 Apr 2020 08:16:31 GMT
If-None-Match: W/"121-171ca289ebf"
它们表达了下面的信息:
- If-Modified-Since: Thu, 30 Apr 2020 08:16:31 GMT,上次修改时间
- If-None-Match: W/“121-171ca289ebf”,资源编号
缓存已经无效
如果是第一种情况——缓存已经失效,那么非常简单,服务器再次给予一个正常的响应(响应码200 带响应体),同时可以附带上新的缓存指令,这就回到了上一节——来自服务器的缓存指令
这样一来,客户端就会重新缓存新的内容
缓存仍然有效
但如果服务器觉得缓存仍然有效,它可以通过一种极其简单的方式告诉客户端:
- 响应码为304 Not Modified
- 无响应体
- 响应头带上新的缓存指令,见上一节——来自服务器的缓存指令
这样一来,就相当于告诉客户端:「你的缓存资源仍然可用,我给你一个新的缓存时间,你那边更新一下就可以了」
总结
服务器视角
服务器无法知道客户端到底有没有像浏览器那样缓存文件,它只管根据请求的情况来决定如何响应
很多后端语言搭建的服务器都会自带自己的默认缓存规则,当然也支持不同程度的修改
浏览器视角
浏览器在发出请求时会判断要不要使用缓存
当收到服务器响应时,会自动根据缓存指令进行处理