在web应用开发的过程中,缓存很重要,其中有的缓存是浏览器和http服务器自身有规定的,有时候,了解这些规定可以让我们在开发过程中更加得心应手,特别是在更新服务器资源时候,比如图片或者是js,css之类的,如果不及时起作用,被用户所看到,是很让人烦恼的,这个时候,就应该了解下这些规则.
结合我自己遇到的经常性的情况,讲四个请求头和使用.它们是Expires
,Cache-Control
,Last-Modified
,Etag
.
浏览器和服务器自身缓存的运行法大概是:
第一次请求服务器,无缓存,所有的资源都是从服务器传输到浏览器,而后,浏览器会对资源做本地的缓存;再次刷新页面的时候,浏览器就会检查一些关于是否过期的限定,如果判定为没有过期,就会读取本地的缓存;如果判定过期了,那么就会发送请求到服务器,读取资源;到服务器之后,就会进行对该文件的判断,看是否有变动,如果有变动,就会传输新的文件给浏览器,浏览器将新的文件缓存;如果没有变动,就会返回一个状态码(不返回文件),给浏览器,让浏览器继续读取缓存的文件.
测试的服务器可以用nginx或者apache都行.都可以设定响应头
来达到测试的目的.
- Expires(http1.0)
决定的是是否使用浏览器本地的缓存.设定的是过期的时间点,如果超过了所设定的时间,那么即不使用浏览器本地的缓存.将会向服务器发送请求了,是格林威治时间,有局限性,如果设定的时间点很超前,比如Expires:Sat,09 Mar 1918 17:01:10 GM
,那么,本地的缓存将一直不能够生效了.
设定的格式是:
Expires:Sat,09 Mar 2018 17:01:10 GM
如果在此时间之内,除了第一次的请求外,其余次数的同个资源请求,将使用本地的缓存,此事状态码将是:200 (from cache)
.
如果超过这个时间点,那么,将不会再用本地资源,将发送请求给服务器了.此时,将要看服务的缓存控制头了(下面有讲述),如果资源没发生变化,那么,将返回状态码304(not modified)
,告诉浏览器,这个文件并没有变化,继续读取缓存即可.
- Cache-Control(http1.1)
有很多的选项,比如:max-age=10
,代表从第一次200成功之后,10s内都读取浏览器缓存,10s后就不再读取浏览器,而是要发送请求给服务器.no-cache
代表不使用缓存等,也是决定了浏览器是否使用本地的缓存,如果发生了改变,那么状态码200
,相当于资源重新从服务器下载传输到客户端并且 重新缓存了.
设定的格式:
Cache-Control:max-age=10
代表第一次从服务器读取了资源后,10s内,都读取缓存,状态码200 (from cache)
,10s后,就再次向服务器发送请求,如果资源变化,就返回状态码200
,然后资源是从网络重新下载的,并且刷新了缓存;如果资源没有变化,那么,就返回状态码304 (not modified)
,继续读取缓存的,从而节约流量.之后,10s内
,继续读取缓存,10s后
,重新请求服务器,如此循环.
- Last-Modified(http1.0)
从资源的响应头里面返回,是格林威治时间,是这个资源的最后的修改的时间,用于当浏览器的缓存(Expires,Cache-Control)
失效时候,请求发送到服务器,服务器就检查文件的Last-Modified
是否有改变,若改变了,那么就重新返回给浏览器新的资源,状态码200
,如果没有变,就返回给浏览器304(not modified)
,让浏览器继续使用缓存.是服务器对使用缓存与否的判断.
但是有个弊端,决定了http1.1协议新出了一个Etag
.由于其使用格林威治时间,精确到秒,如果在同一秒内改变了文件,那么是无法判断为modified
的.
在我的实践中,它不用我去亲手配置.
- Etag(http1.1)
感觉效果和Last-Modified
比较像,都是用于服务器端判断资源是否改变而提示浏览器是否继续使用缓存的,它的判断更加的精确,不会由于时间很近而产生误判.它给每个文件一个独一无二的标志,每次有请求过服务器时候,对比判断标志即可.
当然,在请求头
里,有两个属性:
If-Modified-Since:Mon, 22 Feb 2018 10:20:16 GMT
If-None-Match:"2a85-582b5496ef5eb"
就是配合服务器的Last-Modified
和Etag
的对比而存在的,每次请求到服务器都会和文件的Last-Modified
和Etag
进行对比看是否发生变化来进行下一步操作.它们在第一次请求(无缓存)时候是没有的,当第一次请求后响应头
中带了Last-Modified
和Etag
之后,之后的请求头
就会携带它们,以便到服务器时候可以对比.
关于他们的优先值(这个我倒是未验证):
http1.1>http1.0
其余的部分,只要知道上述的缓存的整个思路,就并不存在其他问题了.