接着上文,这一次我们来聊聊http缓存头。这个问题也是时常会在面试中出现的。
http缓存发展分为了两个阶段。http1.0阶段,基本上通过expries来进行缓存,http1.1阶段,缓存基本上是三组对应的属来进行判断。由于http1.1向下兼容,这里就以http1.1为蓝本来进行讨论。
这两个属性都是用来设置文件过期时间,典型的设置方法如下,详情可以参考 这里
Expires: Fri, 30 Oct 1998 14:19:41
Cache-Control: max-age=3600, must-revalidate
当每次需要拉取文件时,浏览器会判断文件是否超时,如果超时将发起请求,如果未超时就不发起请求或者发起200(from cache)的请求(304的情况后面会说到),cache-control是http1.1标准的,所以对其中的配置参数比expries要丰富,当两者都存在时,先判断cache-control,再执行expries。
当然,如果客户端需要显示的声明该文件不需要缓存,可以使用meta标签来告诉浏览器,文件不需要缓存,每次都从服务器拉取最新的,具体写法如下:
这一对http缓存都用于判断文的最后修改时间,以断定文件是否已经过期,需要从服务器重新拉取。
每次服务器返回文件后,会返回last-modified的http response头部,这个值会说明当前文件的最后修改时间。而if-modified-since是一个require头部,他会向服务器询问在头部给定时间之前文件是否有改变。
这两个属性的工作方式一般如: 1、浏览器向服务器发起请求,服务器会返回带有last-modified response头部的请求,典型写法如:Last-Modified:Tue, 17 May 2016 08:13:58 GMT。
2、浏览器再次向服务器请求时,可以带上if-modified-since头部,并将之前last-modified的服务器时间带回
3、服务器发现在该时间之后文件有改动,则会返回文件,如果没有改动,则会返回一个304,告诉浏览器文件没有变更。
由于304的返回包远小于返回整个文件,所以这里其实是http1.1做了优化的地方。
由于2中所提到的last-modified/if-modified-since头部,最小单位精确到“秒”,无法满足部分高精度需求,所以,诞生了etag/if-none-match这一对够精确判断文件是否改变的值,它们主要通过比对HASH值来进行判断文件是否被修改。
这一对头部除了精度外,工作方式基本和二中提到一对头部类似。
Expires/Cache-Control 是控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。
Last-Modified/If-Modified-Since和ETag/If-None-Match是浏览器发送请求到服务器后判断文件是否已经修改过,如果没有修改过就只发送一个304返回浏览器,告诉浏览器直接从自己本地的缓存取数据,如果修改过那就整个数据重新发给浏览器。
所以,缓存机制可以简单的优先级排列为: Cache-Control > Expires > ETag/If-None-Match == Last-Modified/If-Modified-Since。