如何使用 HTTP 头部缓存指令控制浏览器缓存

发布:elantion 日期:2019-05-07 阅读:482 评论:0

服务器告诉浏览器那些资源需要缓存、缓存多长时间、什么时候更新,都是通过http的头部指令来实现,浏览器对此已经有一套非常成熟的方案,但指令有那么多,我们该怎么选择使用呢?
以下指令不仅仅可以用来给服务器告诉浏览器缓存,反过来,浏览器也可以通过请求的头部指令来告诉服务器缓存,但下面的说明只针对服务器的response头。
另外,缓存指令跟别的大多数头部指令一样,都不介意大小写,对头部指令用法不熟悉的朋友可以请教谷歌或百度。下面的介绍只作一个大概的说明和对比,为的是让大家心中有个概念,如果想非常深入的了解,还得请教 MDN:https://developer.mozilla.org/

Cache-Control

这个指令是当前用得最多,也是最重要的指令,基中有几个值比较常用。

no-cache, no-store

两个都表示不缓存内容,基中no-cache会强制要求服务器校验内容是过期,如果过期就必须重发,否则会返回304响应码,表示内容是最新的,不必重新下载,而no-store则不管什么情况,全部重新发送。
一般来说,为了节约流量,对于静态资源,极少使用no-store,但在接口API则用得比较多,可以保障数据是新鲜的。

max-age

表示一段时间内浏览器会直接取缓存的内容,不发送请求,直到时间到了,才会向服务器请求新内容。用一个比较长的时候可以大大减少请求数量,但会导致发布新内容不能即时更新到客户端,所以静态内容的名称必须带上hash值,可以强制刷新内容。

Expires

表示内容在设定的时间后认为是过期的,例如:Expires: Wed, 21 Oct 2015 07:28:00 GMT,表示2015年10月21日7点28分过期,这个时间后必须向服务器请求新内容。
如果,response中带有cache-control: max-age,即这个指定会被无视。

检查是否陈旧内容的指令

如果cach-control设置了no-cache或者其它需要校验内容是否陈旧的值,那就需要附加其它用于校对的指令,其中最常用的是ETag, Last-Modified

Last-Modified

表示这个内容最后的编辑时间,如果服务器收到的值早于现存内容的时间,就会向浏览器重新发送新内容。可以配合 If-Modified-Since 和 If-Unmodified-Since 这两个指令一起用。

ETag

表示内容的编号,如果服务器收到的编号与当前内容的编号不一样,就会向浏览器重新发送新内容。一般来说,我们只需要设置ETag即可,它既准确又容易理解。

最佳实践

设置头部缓存指令的最终目的就是减少请求数量,减少重新下载的次数,但必须保证页面内容是最新的。
对于静态内容,建议除了html文件外,其它静态内容都设置cache-controlmax-age值,最好是一个非常大的值,例如一年,这样用户只需下载一次后,很长一段时间都不再需要再次下载,甚至不需要向服务器校验文件是否陈旧,大大减少请求数量。同时,为了保证文件可以更新,这些静态文件的文件名必须带有随机字符串,例如hash值。
对于html文件,建议设置cache-controlno-cache,同时带上ETag指令,这样用户每次请求页面只需要校验html是否最新即可,不必每次全部内容下载。
但无论如何优化,头部指令都无法做到离线加载,这个就需要PWA技术才可以实现了,我们下一节来研究研究。