You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
并且返回头中的 Date 表示消息发送的时间,表示当前资源在 Date ~ Date +3600s 这段时间里都是有效的。不过我在实际使用中常常遇到设置了 max-age 之后,在 max-age 时间内重新访问资源却会返回 304 not modified ,这是由于服务器的时间与本地的时间不同造成的。
我觉得这段表述的不太准确,Date确实是服务器响应时间,但是与资源的有效期无关。资源的有效期应该是:客户端接收到资源的时间点到3600s之间的这段时间,max-age相对的是客户端接收到响应的时间,而不是Date。这也就解释了你所描述的在 max-age 时间内重新访问资源却会返回 304 not modified的这一现象,原因就是服务器时间比客户端时间要快一些。 @yiliang114
Activity
yiliang114 commentedon May 1, 2019
答案:
这里说的缓存是指浏览器(客户端)在本地磁盘中对访问过的资源保存的副本文件。
浏览器缓存主要有以下几个优点:
浏览器缓存分为强缓存和协商缓存,两者有两个比较明显的区别:
chrome
中强缓存(虽然没有发出真实的http
请求)的请求状态码返回是200 (from cache)
;而协商缓存如果命中走缓存的话,请求的状态码是304 (not modified)
。 不同浏览器的策略不同,在Fire Fox
中,from cache
状态码是 304.请求流程
浏览器在第一次请求后缓存资源,再次请求时,会进行下面两个步骤:
header
中的信息,根据response header
中的expires
和cache-control
来判断是否命中强缓存,如果命中则直接从缓存中获取资源。IF-Modified-Since
或者IF-None-Match
, 它们的值分别是第一次请求返回Last-Modified
或者Etag
,由服务器来对比这一对字段来判断是否命中。如果命中,则服务器返回 304 状态码,并且不会返回资源内容,浏览器会直接从缓存获取;否则服务器最终会返回资源的实际内容,并更新 header 中的相关缓存字段。借用网上的一张图片
强缓存
强缓存是根据返回头中的
Expires
或者Cache-Control
两个字段来控制的,都是表示资源的缓存有效时间。Expires
是http 1.0
的规范,值是一个GMT
格式的时间点字符串,比如Expires:Mon,18 Oct 2066 23:59:59 GMT
。这个时间点代表资源失效的时间,如果当前的时间戳在这个时间之前,则判定命中缓存。有一个缺点是,失效时间是一个绝对时间,如果服务器时间与客户端时间偏差较大时,就会导致缓存混乱。而服务器的时间跟用户的实际时间是不一样是很正常的,所以Expires
在实际使用中会带来一些麻烦。Cache-Control
这个字段是http 1.1
的规范,一般常用该字段的max-age
值来进行判断,它是一个相对时间,比如 .Cache-Control:max-age=3600
代表资源的有效期是 3600 秒。并且返回头中的Date
表示消息发送的时间,表示当前资源在Date ~ Date +3600s
这段时间里都是有效的。不过我在实际使用中常常遇到设置了max-age
之后,在max-age
时间内重新访问资源却会返回304 not modified
,这是由于服务器的时间与本地的时间不同造成的。当然Cache-Control
还有其他几个值可以设置, 不过相对来说都很少用了:no-cache
不使用本地缓存。需要使用协商缓存。no-store
直接禁止浏览器缓存数据,每次请求资源都会向服务器要完整的资源, 类似于network
中的disabled cache
。public
可以被所有用户缓存,包括终端用户和 cdn 等中间件代理服务器。private
只能被终端用户的浏览器缓存。如果
Cache-Control
与Expires
同时存在的话,Cache-Control
的优先级高于Expires
。协商缓存
协商缓存是由服务器来确定缓存资源是否可用。 主要涉及到两对属性字段,都是成对出现的,即第一次请求的响应头带上某个字,
Last-Modified
或者Etag
,则后续请求则会带上对应的请求字段If-Modified-Since
或者If-None-Match
,若响应头没有Last-Modified
或者Etag
字段,则请求头也不会有对应的字段。Last-Modified/If-Modified-Since
二者的值都是GMT格式的时间字符串,Last-Modified
标记最后文件修改时间, 下一次请求时,请求头中会带上If-Modified-Since
值就是Last-Modified
告诉服务器我本地缓存的文件最后修改的时间,在服务器上根据文件的最后修改时间判断资源是否有变化, 如果文件没有变更则返回304 Not Modified
,请求不会返回资源内容,浏览器直接使用本地缓存。当服务器返回304 Not Modified
的响应时,response header
中不会再添加的Last-Modified
去试图更新本地缓存的Last-Modified
, 因为既然资源没有变化,那么Last-Modified
也就不会改变;如果资源有变化,就正常返回返回资源内容,新的Last-Modified
会在response header
返回,并在下次请求之前更新本地缓存的Last-Modified
,下次请求时,If-Modified-Since
会启用更新后的Last-Modified
。Etag/If-None-Match
, 值都是由服务器为每一个资源生成的唯一标识串,只要资源有变化就这个值就会改变。服务器根据文件本身算出一个哈希值并通过ETag
字段返回给浏览器,接收到If-None-Match
字段以后,服务器通过比较两者是否一致来判定文件内容是否被改变。与Last-Modified
不一样的是,当服务器返回304 Not Modified
的响应时,由于在服务器上ETag
重新计算过,response header
中还会把这个ETag
返回,即使这个ETag
跟之前的没有变化。为什么要有 Etag
HTTP1.1
中Etag
的出现主要是为了解决几个Last-Modified
比较难解决的问题:If-Modified-Since
能检查到的粒度是秒级的,使用Etag
就能够保证这种需求下客户端在1秒内能刷新 N 次 cache。优先级
用户行为对缓存的影响
简单说就是 F5 刷新的时候,会暂时禁用强缓存经过对qq、fire fox 、safari 、chrome 这几个浏览器的访问同一个页面测试我发现,不同的浏览器在 F5 刷新的时候 ,同一个文件 qq 、fire fox 浏览器会返回
304 Not Nodified
,在请求头中不携带Expires/Cache-Control
; 而 chrome 和 safari 刷新的时候,会返回200 from cache
, 没有真正发起请求,走强缓存。可见不同的浏览器反馈是不一致的,所以下面表格中"F5刷新"时Expires/Cache-Control
会无效我认为是存在一定争议的。而 Ctrl + F5 强制刷新的时候,会暂时禁用强缓存和协商缓存。
如何设置强缓存和协商缓存
后端服务器,写入代码逻辑中:
Nginx
配置一般来说,通过 nginx 静态资源服务器,会默认给资源带上强缓存、协商缓存的 header 字段。
两个示例
如果在
cache-control
定义的max-age
时间之内,js
,css
文件会走强缓存,http
状态码是 200, 跟服务器也并不会有交互。但是第一个文件index.html
文件, 每次回车或者刷新都是状态码都是 304 ,因为它的请求头中默认每次都携带了Cache-Control: max-age=0
。js
css
文件cache-control
超时之后,重新按回车会走协商缓存,请求服务器发现资源没有改变,于是返回 304 ,浏览器从缓存中获取内容,从size
中也可以看出端倪, 几百 B 的包不是静态资源的体积。三级缓存原理(大白话)
最后总结一下浏览器的三级缓存原理:
先去内存看,如果有,直接加载
如果内存没有,择取硬盘获取,如果有直接加载
如果硬盘也没有,那么就进行网络请求
加载到的资源缓存到硬盘和内存
参考文档
from disk cache 与 from memory cache
http协商缓存VS强缓存
acodercc commentedon May 1, 2019
图文并茂,条理清晰,赞用心的写作
[-]To zhijianzhang: 浏览器的强缓存和协商缓存(阿里)[/-][+]To yiliang114: 浏览器的强缓存和协商缓存(阿里)[/+][-]To yiliang114: 浏览器的强缓存和协商缓存(阿里)[/-][+]阿里巴巴: 浏览器的强缓存和协商缓存(一面)[/+][-]阿里巴巴: 浏览器的强缓存和协商缓存(一面)[/-][+]阿里巴巴:浏览器的强缓存和协商缓存(一面)[/+]ZhengMengSi commentedon Jan 31, 2021
我觉得这段表述的不太准确,Date确实是服务器响应时间,但是与资源的有效期无关。资源的有效期应该是:客户端接收到资源的时间点到3600s之间的这段时间,max-age相对的是客户端接收到响应的时间,而不是Date。这也就解释了你所描述的在 max-age 时间内重新访问资源却会返回 304 not modified的这一现象,原因就是服务器时间比客户端时间要快一些。 @yiliang114