缓存类型私有缓存是指缓存不会与其他用户共享缓存代理缓存是中间代理服务器的缓存,但是因为https的普及,这些代理服务器基本上只能forwardrequestsManagedcached是源服务器配置的缓存:nginx、cdn、serviceworker,当响应的状态码为1xx、2xx、3xx、4xx时可以缓存什么样的请求响应,没有no-在5xx范围内存储指令。响应中包含Expire字段或者以下说明:public,private,max-age,s-maxage,immutable等缓存响应key一般使用requestmethod+requestedURI作为缓存key,但是也可以使用vary字段添加响应标头作为密钥的一部分。例如:Vary:Accept-LanguageFreshness只要响应的年龄没有超过它的新鲜度生命周期,就被认为是“新鲜的”,否则就被认为已经过期。新鲜度生命周期是指从服务器产生响应到其过期时间的时间范围。explicitexpirationtime是指响应头包含Expires字段或者max-age指令age是指服务产生响应后经过的时间。浏览器也可以使用max-age或者min-fresh请求指令,建议服务器返回相应的响应(比如浏览器强制刷新时,会带上max-age=0)FreshnessLifetime(新鲜度生命周期计算)如果缓存是共享的并且响应头中也包含s-maxage,则使用该值。如果响应头中包含max-age,则使用该值。如果响应标头包含Expires,则使用此字段减去Date字段(如果Date字段不存在,则使用收到响应的时间)否则如果响应标头中没有明确的过期时间,则启发式应用。FreshnessLifetime来计算如果响应头中有多个Expires或者多个Cache-Control:max-age,可以使用第一个字段的值或者认为响应已经过时(行为未定义,参考实际行为浏览器),如果缓存指令冲突,例如(max-age和no-cache同时出现),只会应用最严格的指令;如果max-age是无效值,响应也会被认为是Stale的CalculatingHeuristicFreshness(新鲜度的启发式计算)。主要原因是服务器可能没有提供明确的过期时间(没有Expires和max-age),所以这时候缓存自己需要为文件计算一个过期时间,比如使用其他字段Last-Modifiedtime来辅助计算,但是这里不会给出固定的算法,需要浏览器自行定义不过还是给个参考:(Last-Modified-Date)*10%(可以认为如果过了这么一段时间再修改,下一次修改很可能就在这个时间内,所以生命周期也在这个时间范围内)年龄计算age_value响应头Age字段,如果没有则认为是0date_value响应头Date字段now当前时间request_time请求时间response_time计算响应时间apparent_age主要有两种方式,response_time减去date_value,如果浏览器时间与服务器时间相同同步应该更准确(但不太可能)apparent_age=max(0,response_time-date_value);corrected_age_value(只要支持http1.1以上的,都采用这种计算方式)response_delay=response_time-request_time;corrected_age_value=age_value+response_delay;那么corrected_age_value也可以作为corrected_initial_age,但是还有一种情况是返回头中没有Age字段(age_value被认为是0参与corrected_age_value的计算),corrected_initial_age可以通过下面的保守方式计算,并且分别计算apparent_age和corrected_age_value,然后计算最大值:corrected_initial_age=max(apparent_age,corrected_age_value);resident_time=now-response_time;current_age=corrected_initial_age+resident_time;ServingStaleResponses如果响应头包含no-cache、must-revalidate、s-maxage和proxy-revalidate,则禁止缓存返回过期的响应只允许返回过期的响应,除非浏览器无法与服务器建立连接,或者请求有一个max-stale指令验证(验证资源)如果响应应该缓存(即必须缓存的response会进入校验阶段,关系到response是否可以缓存),缓存过期,或者不能被选中(具体原因后面补充)),需要使用条件请求机制(conditionalrequestverificationmechanism)发送请求让服务器返回一个新的responseSendingaValidationRequestSendingavalidationrequestcache会合成一个request,copymethod,uri等header字段标记通过vary字段,添加If-Modified-Since、If-Unmodified-Since、If-Match、If-None-Match这些前置条件头;这里f-Match、If-None-Match优先于If-Modified-Since、If-Unmodified-Since更高(毕竟验证更准确)处理一个ValidationResponse304状态码,不返回响应内容或完整的response也可以是5xxCache-Controlcache-control指令可以分别在request/response中生效,即cache-control可以出现在requestheader/responseheader中,request和response中它们支持的指令不一定是相同,即使指令相同,意思也不一定相同。ResponseDirectives当返回带有以下指令时,缓存必须按照这些指令进行处理max-age表示新鲜度时间范围。当响应的age超过这个范围时,就被认为过期了,但是响应的age并不是根据当前时间减去收到响应的时间来计算的。must-revalidate指出一旦响应缓存过期,必须重新生效后才能使用。任何情况下都禁止使用过期的响应缓存。因为有可能在服务器无法连接的情况下使用过期的响应缓存来回复请求,所以must-revalidate会禁止这种情况,直接返回一个504。一般情况下,错误码需要和max-age配合使用。must-understand指出,如果缓存根据状态码理解应该缓存响应,则应该缓存响应。通常,must-understand将与no-store一起使用。Cache-Control:must-understand,no-store如果缓存不支持must-understand,然后使用no-store指令ifcachesupportmust-understand,它根据其状态码存储对缓存要求的理解的响应no-cache表示响应缓存必须通过验证并接收(成功响应)成功的响应是用的,意思是每次使用缓存前都需要向服务器发送验证请求进行验证。注意no-cache并不代表“不缓存”,no-cache的意思是响应仍然可以被缓存但是必须在使用缓存之前重新生效真正的“不缓存”是no-store指令no-store表示私有缓存和共享缓存都不应该缓存响应no-transform因为一些中间服务器会将内容转换成各种格式,例如图片可以是转换成不同的格式以减少传输大小,因此这里将禁止这种行为。private表示响应只能存在于私有缓存中。只要返回的资源中有与用户相关的个人信息,就应该使用这个指令来减少个人信息泄露。proxy-revalidate与must-validate相同,但仅对共享缓存有效。Public表示响应应该缓存在共享缓存中。s-maxage与max-age类似,但只对共享缓存有效。Immutable表示响应在生命周期内不会更新内容。一般情况下,当强制刷新时浏览器(即使缓存还没有过期)都会向服务器发送请求进行验证。当缓存还没有过期(还在生命周期内),即使强制刷新,也不会发送请求去验证(因为没必要)。这适用于版本永不更新的stale-while-revalidate资源,表示过期缓存在缓存过期后仍然可以使用一段时间,在此期间资源会在后台重新生效。这样做的好处是减少直接revalidate,提高用户体验,因为都是在后台revalidateCache-Control:max-age=604800,stale-while-revalidate=86400缓存在604800秒后过期,但是过期的缓存可以在接下来的86400秒内仍然会被使用,并且还会在这段时间内在一定时间内在后台执行revalidatestale-if-error来指出过期的缓存。如果服务器在revalidate期间返回(500、502、503或504),它仍然可以使用一段时间。到时候过了这段时间还是会进入正常到期。ProcessRequestDirectives当requestheader中伴随着如下指令时,表示这是对缓存的请求的期望,但并不一定要满足max-age才能让缓存返回其life的缓存周期在一定的时间范围内。很多浏览器会使用max-age=0来强制刷新max-stale让缓存返回过期时间在一定范围内的缓存min-fresh指出cac他返回的缓存在其生命周期中至少有一定的时间。如果小于这个时间,则禁止使用缓存,但是大多数浏览器不支持no-cache这个命令。Requestcachetorevalidateno-storebeforeusethecache让缓存不缓存响应,即使响应是可以缓存的no-transform。Response的only-if-cached命令表示要获取缓存的response,所以如果缓存已经缓存了资源,直接返回即可。想想max-age=0和no-cache的区别是max-age=0,只会让缓存失效。一般情况下还是需要revalidate,但是浏览器在无法连接服务器的情况下仍然可以返回过期的缓存,禁止no-cache。因为这个行为,no-cache更等同于must-revalidate,max-age=0如何去除浏览器缓存一旦产生了缓存,就没有完美的去除方法,因为期间不会有缓存effectiveperiod请求直接进入服务器(除非设置了no-cache,must-revalidate)。一种方法是使用POST请求请求相同的url使缓存失效,但是这种方法比较麻烦。另一种方法是使用Clear-Site-Data响应头字段例如:Clear-Site-Data:cache可以清除缓存、cookies、存储、executionContexts但不是所有浏览器都支持(safari不支持)。网页加载性能和提升整体体验,但这也意味着开发者没有办法实现对页面的绝对控制(例如,没有办法让所有用户在访问时立即体验到页面代码更新,除非没有-cache等指令用于强制每一个请求都去重新生效)Refererhttps://developer.mozilla.org...https://www.rfc-editor.org/rf...https://www.rfc-editor.org/rf...
