By Noxxxx from https://interview.noxxxx.com/?post_type=post&p=23 上山打老虎
欢迎分享与聚合,尊重版权,可以联系授权
缓存指令分为请求阶段和响应阶段
访问场景:
Chrome 中访问 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control,并且 Network 中设置 Disable cache。
状态码
200
Request Headers
cache-control: max-age=0
或者是
cache-control: no-cache
Response Headers
cache-control: max-age=86400, public
etag: W/"e3e3ffb3aad7d8d28157eecff7bbec41"
last-modified: Fri, 10 Mar 2023 00:42:11 GMT
访问场景:
Chrome 中访问 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control,并且 关闭 Network 中的 Disable cache
状态码
304
Request Headers
cache-control: max-age=0 if-modified-since: Fri, 10 Mar 2023 00:42:11 GMT if-none-match: W/"e3e3ffb3aad7d8d28157eecff7bbec41"
Response Headers
cache-control: max-age=86400, public
etag: W/"e3e3ffb3aad7d8d28157eecff7bbec41"
last-modified: Fri, 10 Mar 2023 00:42:11 GMT
字段认知
Cache-control
缓存请求指令
Cache-Control: max-age=<seconds>
Cache-Control: max-stale[=<seconds>]
Cache-Control: min-fresh=<seconds>
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: only-if-cached
缓存响应指令
Cache-control: must-revalidate
Cache-control: no-cache # 在发布缓存副本之前,强制要求缓存把请求提交给原始服务器进行验证 (协商缓存验证)
Cache-control: no-store # 缓存不应存储有关客户端请求或服务器响应的任何内容,即不使用任何缓存
Cache-control: no-transform
Cache-control: public # 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存,即使是通常不可缓存的内容
Cache-control: private # 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。私有缓存可以缓存响应内容,比如:对应用户的本地浏览器
Cache-control: proxy-revalidate
Cache-Control: max-age=<seconds> # 设置缓存存储的最大周期,超过这个时间缓存被认为过期 (单位秒)。与Expires相反,时间是相对于请求的时间
Cache-control: s-maxage=<seconds>
Last-Modified: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT # 源头服务器认定的资源做出修改的日期及时间,精确度比 ETag 要低
ETag: W/"<etag_value>" 或 "<etag_value>"
If-None-Match: <etag_value>, <etag_value>, … 或 *
通常我们需要对缓存响应指令中的上述几个进行认知,其余的在特定场景下才会用到。
首先要纠正一点的是,【强缓存和协商缓存】这个说法其实过于片面了,本质上这是浏览器的一种缓存策略,至于如何确定缓存怎么取?怎么读?则是根据不同的字段来定的,【强缓存和协商缓存】的说法过于将这种策略解释为某一具象的东西。
更合适的理解其实是优先级的关系,首先浏览器会根据请求 Headers 中的 cache-control 的内容,决定是否需要走进一步的缓存策略(也就是我们俗称的协商缓存),如果不需要进一步向服务器确认资源的新鲜度,那么就直接从本地 Memory 或者 disk 里读取,否则进行二次确认,二次确认的过程中涉及到 If-None-math, If-Modified-SInce 这些字段的配合来让服务器判定资源和上一次的相比是否真正过期,如果不过期则返回 304 Code,如果过期则返回新的资源以及缓存响应 Headers。
