为方便理解,我们认为浏览器存在一个缓存数据库,用于存储缓存信息。
在客户端第一次请求数据时,此时缓存数据库中没有对应的缓存数据,需要请求服务器,服务器返回后,将数据存储至缓存数据库中。
通过复用以前获取的资源,可以显著提高网站和应用程序的性能。Web 缓存减少了等待时间和网络流量,因此减少了显示资源表示形式所需的时间。通过使用 HTTP缓存,变得更加响应性。
缓存规则解析
- 强制缓存
- 对比缓存
我们可以看到两类缓存规则的不同,强制缓存
如果生效,不需要再和服务器发生交互,而对比缓存
不管是否生效,都需要与服务端发生交互。
两类缓存规则可以同时存在,强制缓存
优先级高于对比缓存
,也就是说,当执行强制缓存
的规则时,如果缓存生效,直接使用缓存,不再执行对比缓存
规则。
强制缓存
对于强制缓存来说,响应header中会有两个字段来标明失效规则(Expires/Cache-Control
)
字段 | 用途 | 实例 |
---|---|---|
Expires | 强缓存的过期日期 | Expires:Thu,06 Aug 2021 14:36:18 GMT |
Cache-Control | 指定指令实现缓存机制 | Cache-Control:max-age=60 |
Cache-control 头
HTTP/1.1 定义的 Cache-Control
头用来区分对缓存机制的支持情况,
- 没有缓存
Cache-Control: no-store
- 缓存但重新验证
Cache-Control: no-cache
此方式下,每次有请求发出时,缓存会将此请求发到服务器(译者注:该请求应该会带有与本地缓存相关的验证字段),服务器端会验证请求中所描述的缓存是否过期,若未过期(注:实际就是返回304),则缓存才使用本地缓存副本
- 私有和公共缓存
Cache-Control: private Cache-Control: public
“public” 指令表示该响应可以被任何中间人(译者注:比如中间代理、CDN等)缓存。若指定了”public”,则一些通常不被中间人缓存的页面(译者注:因为默认是private)(比如 带有HTTP验证信息(帐号密码)的页面 或 某些特定状态码的页面),将会被其缓存。
“private” 则表示该响应是专用于某单个用户的,中间人不能缓存此响应,该响应只能应用于浏览器私有缓存中。
- 过期
Cache-Control: max-age=31536000
过期机制中,最重要的指令是 “max-age=
<seconds>
“,表示资源能够被缓存(保持新鲜)的最大时间。相对Expires而言,max-age是距离请求发起的时间的秒数。针对应用中那些不会改变的文件,通常可以手动设置一定的时长以保证缓存有效,例如图片、css、js等静态资源。
Pragma
- Pragma是一个HTTP1.0中规定的通用首部,如果 Cache-Control不存在的话,它的行为与 Cache-Control: no-cache 一致。强制要求缓存服务器在返回缓存的版本之前将请求提交到源头服务器进行协商验证。
- Pragma的值就只有一个,no-cache,并且它的优先级比Cache-Control高。
ETag
ETag
HTTP响应头是资源的特定版本的标识符。这可以让缓存更高效,并节省带宽,因为如果内容没有改变,Web服务器不需要发送完整的响应。而如果内容发生了变化,使用ETag有助于防止资源的同时更新相互覆盖 (“空中碰撞”)
语法:
ETag: W/"<etag_value>"
ETag: "<etag_value>"
例:
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
ETag: W/"0815"
缓存未更改的资源
ETag
头的一个典型用例是缓存未更改的资源。 如果用户再次访问给定的URL(设有ETag字段),显示资源过期了且不可用,客户端就发送值为ETag的If-None-Match header字段:
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
服务器将客户端的ETag(作为If-None-Match字段的值一起发送)与其当前版本的资源的ETag进行比较,如果两个值匹配(即资源未更改),服务器将返回不带任何内容的304未修改状态,告诉客户端缓存版本可用(新鲜)。
如果 http 响应头中 ETag 值改变了,是否意味着文件内容一定已经更改?
答: 不一定,由服务器中 ETag 的生成算法决定。
比如 nginx
中的 etag
由 last_modified
与 content_length
组成,而 last_modified
又由 mtime
组成
当编辑文件却未更改文件内容时 mtime
也会改变,此时 etag
改变,但是文件内容没有更改。