浏览器缓存机制
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 header
中cache-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-store
,max-age
,max-stale
,min-fresh
,only-if-cached
,对响应内容设置了max-age
),如果请求的资源没有过期,则浏览器不会向服务器发起请求,而是直接从浏览器缓存中获取资源;如果请求的资源过期了,则浏览器会向服务器发起请求,等待服务器的响应,如果服务器判定资源没有被修改,则会返回304
状态码,告知浏览器直接取缓存中的数据;如果资源发生了改变,则服务器会返回新的资源,并返回200
状态码(服务器是通过if-Modified-Since
和if-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无效的说法持保留意见
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。