本文作者:IMWeb devinran 原文出处:IMWeb社区 未经同意,禁止转载
在浏览器第一次请求某url获得的返回状态是200的响应头中,获取Last-Modified字段,这个字段标识此文件在服务器端的最后被修改时间,格式类似于:
Last-Modified Thu, 15 Oct 2015 02:45:17 GMT
然后在浏览器第二次请求此url时,浏览器会根据之前获得的Last-Modified向服务器传送If-Modified-Since请求头,询问文件是否有被修改过
If-Modified-Since Thu, 15 Oct 2015 02:45:17 GMT
如果服务器端资源没有变化,则请求返回304。达到缓存效果。
如果服务器端资源发生改变或者重启服务器,则重新响应资源,返回200,与第一次相同。
如果If-Modified-Since的时间比服务器当前时间还晚,则会被认定为非法请求
HTTP协议定义ETag为被请求变量的实体标记,类似于一个资源的hash值,用于对url进行标记。这个值完全取决于服务器,并在响应头中返回浏览器。格式类似于:
Etag 9a932760982d29a83836cbd469bb14e7
第二次请求相同的数据时,浏览器的请求头中带上If-None-Match字段,如果服务器端资源没有变化,则请求返回304。
If-None-Match 9a932760982d29a83836cbd469bb14e7
以上两个方式虽然完成了缓存文件功能,但是每次请求url时还是会向服务器发送一个请求头If-Modified-Since和If-None-Match。使用一些别的策略,可以省略这个请求过程。
Expires是存在于响应头中的字段,它用一个绝对的时间点来指定文件的有效时间,(没有设置其他缓存控制的字段情况下)在有效时间内直接使用本地缓存文件。格式类似于:
Expires Wed, 12 Oct 2016 13:18:42 GMT
Cache-Control定义了一组关于缓存的控制字段,常用的有以下几个:
格式类似于:
Cache-Control private, max-age=31104000
Expires来自于HTTP1.0,Cache-Control来自于HTTP1.1,Cache-Control优先级高于Expires
首先梳理一下,我们需要的是:
所以比较好的一个方案是使用Cache-Control,并且结合文件版本号。即在文件名中嵌入的一个“指纹”。
见上图,将js与css等静态资源设置Cache-Control一年有效期,然后在文件名中加入了一串版本号信息。那么在文件没有变动的时候,浏览器不用发起请求直接可以使用缓存文件;而在文件有变化的时候,由于文件版本号的变更,导致文件名变化,请求的url变了,自然文件就更新了。
补一张Cache-Control策略的图,扒自Google Developers