浏览器缓存机制

Expires策略

Expires是web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存读取数据,而无需再次请求。

Web服务器告诉浏览器在GMT(格林尼治时间):Tue,27 Jun 2017 02:15:13之前,可以使用缓存文件。

Expires是HTTP 1.0定义的内容,现在大多数浏览器默认使用HTTP 1.1,所以它的作用较小。

Cache-Control

1. 缓存控制头 Cache-Control

Cache-Control是HTTP中,控制缓存行为的首部字段。Cache-Control可以控制浏览器是否直接从浏览器缓存存取数据还是重新发送请求到服务器获取数据。Cache-Control的选择项更多,设置更细致,如果同时设置的话,其优先级高于Expires

2. request header中的Cache-Control

request headercache-control的可选值有一下几种:no-cahce,no-store,max-age,max-stale,min-fresh,only-if-cached

在浏览器中,发起请求主要有两种方式:

  • 打开一个链接,浏览器自动会发起一个请求,这个过程中,没有办法指定request header中的cache-control,请求中的cache-control是由浏览器指定的,不同的浏览器的cache-control的值会有不同,通常情况下cache-control的值为max-age=0

  • 在JavaScript中,我们可以通过Ajax来发起请求,并通过xhr.setRequestHeader('cache-control', 'xxx')的方式来指定请求的cache-control的值。

cache-control的值有很多,那么不同的值会如何影响浏览器对请求的处理呢?经过我的测试(使用Chrome、Opera浏览器),在大多数情况下(request header中的cache-control的值为:no-storemax-agemax-stalemin-freshonly-if-cached,对响应内容设置了max-age),如果请求的资源没有过期,则浏览器不会向服务器发起请求,而是直接从浏览器缓存中获取资源;如果请求的资源过期了,则浏览器会向服务器发起请求,等待服务器的响应,如果服务器判定资源没有被修改,则会返回304状态码,告知浏览器直接取缓存中的数据;如果资源发生了改变,则服务器会返回新的资源,并返回200状态码(服务器是通过if-Modified-Sinceif-None-Match来判断资源是否被修改的 )。

但是,存在两种例外情况:

  • 如果在request header中指定cache-control的值为no-cache,则浏览器会向服务器发起请求,向服务器重新请求资源,无论本地资源有没有过期、该资源有没有改变,服务器也会重新传送一次资源。

  • 如果在request header中指定cache-control的值为mag-age=0,则浏览器会向服务器发起请求,等待服务器的响应,如果服务器判定资源没有被修改,则会返回304状态码,告知浏览器直接取缓存中的数据,如果资源发生了改变,则服务器会返回新的资源,并返回200状态码。

3. response header中的Cache-Control

response header中的cache-control指明了浏览器对响应内容的缓存方式

缓存响应指令 说明
no-cache 不缓存过期的资源,在提供缓存资源前必须先向服务器确认有效性
no-store 不缓存响应的任何内容
max-age 响应的最大Age值
public 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存
private 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)
must-revalidate 缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源。
no-transform 代理不可更改媒体类型
proxy-revalidate 要求中间缓存服务器对缓存的响应有效性再进行确认
s-maxage 公共缓存服务器响应的最大Age值,针对缓存服务器

浏览器接受来自服务器的响应,会根据response header中的cache-control来决定对响应内容进行怎样的处理,下面详细说明一些常用的cache-control指令

  • no-cache:no-cache代表的不是不缓存,它的意思是不缓存过期的资源。一个资源的cache-control值为no-cache,当再次请求该资源时,浏览器会向服务器发送请求,确认该资源是否被修改过,如果没有被修改过,服务器返回响应状态码304,浏览器从缓存中取得资源;如果服务器中的资源发生了修改,服务器会返回新的资源,并返回响应状态码200,浏览器从响应体中取得资源

  • no-store:no-store代表的才是不缓存,如果响应的cache-control的值为no-store,则浏览器不会缓存该响应体,当再次请求该资源的时候,浏览器会发送请求,从服务器获取资源。

  • max-age: 当服务器返回的响应的cache-control的值为max-age=xxx时,在max-age指定的时间范围之内,浏览器将不对资源的有效性(服务器中的资源是否发生改变)再作确认,即当再次请求该资源时,浏览器直接从缓存中取得该资源,此时不会向服务器发送请求,但是也会有响应状态码(200 OK from disk cache);当超出max-age指定的时间范围,浏览器会向服务器发送请求,确认服务器中的资源与缓存中的资源是否一致,如果一致,则会返回响应状态码304(Not Modified),浏览器直接从缓存中取得资源,如果服务器端的资源发生了变动,则服务器会返回新的资源和响应状态码200,浏览器从响应体中获取资源。

Last-Modified与if-Modified-Since

Last-Modified表示服务器端文件的最后修改时间,需要和cache-control共同使用,是检查服务器端资源是否更新的一种方式。当浏览器再次进行请求时,会向服务器传送If-Modified-Since报头,询问Last-Modified时间点之后资源是否被修改过。如果没有修改,则响应状态码码为为304,使用缓存;如果修改过,则再次去服务器请求资源,响应状态码码为200,资源为服务器最新资源。

Etag与if-None-Match

ETage是服务器根据实体内容生成一段hash字符串,能够标识资源的状态,能够更加准确的控制缓存。当浏览器再次请求时,会向服务器传送if-None-Match报头,服务器会比较资源的ETage值与if-None-Math的值,来判断资源是否已经修改,如果没有修改,则响应状态码码为304,使用缓存;如果修改过,则返回最新资源,响应状态码为200,资源为服务器最新资源。

Last-Modified与ETag比较

Last-modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续对比Last-modified。最后才决定是否返回304.

使用ETag可以解决Last-modified存在的一些问题:

1. 某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新 
2. 如果资源修改非常频繁,在秒以下的时间内进行修改,而Last-modified只能精确到秒 
3. 一些资源的最后修改时间改变了,但是内容没改变,使用ETag就认为资源还是没有修改的。

使用缓存流程

强缓存与协商缓存

  • 强缓存:不发送请求到服务器确认资源是否有效,直接从缓存中取得资源

  • 协商缓存:从缓存中取资源前,先向服务器发送请求,确认资源是否有效(过期),如果资源有效(资源没有改动),则服务器返回响应状态码304,告知浏览器本地缓存可以继续使用;如果资源失效(资源发生了改动),则服务器返回新的资源和响应状态码200,此时不使用本地失效的资源。

用户行为对缓存的影响

盗用网上的一张图,来说明用户行为对缓存的影响

  • 经过测试,对F5刷新会导致Expires/Cache-Control无效的说法持保留意见

参考资料

浅谈Web缓存
Web浏览器的缓存机制
MDN: Cache-Control

jhhfft 作者 · 9月7日

回复

载入中...
jhhfft jhhfft

290 声望

发布于专栏

每日技术笔记

记录前端学习的点点滴滴

14 人关注