浏览器缓存策略回顾
Posted mife
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浏览器缓存策略回顾相关的知识,希望对你有一定的参考价值。
最近一些面试中,会涉及到一些关于浏览器中静态资源的缓存的问题,在此做一个简单梳理。
1. 减少网络带宽消耗,当web缓存副本被使用时,只会产生极小的网络流量;
2. 可以避免重复的网络请求,降低了对服务器的压力;
等等。最终的最终,就是要做到用户体验的提高!提高!提高!
浏览器缓存的控制,分meta标签和http消息头两种,由于用meta标签浏览器兼容较差,故在此主要聊下http消息头。
浏览器缓存静态资源的过程中有两种缓存策略,下边分别简述。
强缓存
这意味着,浏览器直接从本地缓存中获取数据,不与服务器进行交互。
其中涉及到最关键的两个属性是Expires和Cache-Control。
Expires是HTTP1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略;
Expires规定了缓存失效时间(Date为当前时间),是绝对时间。
由于Expires返回的是一个绝对时间,在服务器时间与客户端时间相差较大的时候,缓存命中不准确;
在cookie上也有Expires和max-age,规则和静态资源
的基本一致,但是cook
ie过期是自动清除的,而静态资源不会。
下图是 Cache-Control的多种指令汇总:
下图表述了它们之间的逻辑关系:
特别注意,
no-cache
和
no-store
哦
。
首先,浏览器第一次向服务器请求一个资源,服务器在返回这个资源的同时,在response的header会加上Expires/Cache-Control,如之前截图。
然后, 浏览器再次请求这个资源时,先从缓存中寻找,找到这个资源后,比较Cache-Control的max-age字段值或者Expires做比较, 如果在有效期内,则读取缓存内容;若缓存已过期,则重新向服务器发送请求;
强缓存在浏览器的状态码为:200 OK(from disk cache)或是200 OK (from memory cache),如下图:
其中,memory cache是内存缓存,disk cache是磁盘缓存。
在浏览器中,通常,浏览器会在js和图片等文件解析执行后直接存入内存缓存中,那么当刷新页面时只需直接从内存缓存中读取(from memory cache);而css文件则会存入磁盘文件中,所以每次渲染页面都需要从磁盘读取缓存(from disk cache)。但是,也不绝对是这样的,比如: <link rel="preload"> 这些显式指定的预加载资源,就会被放入memory cache中。
协商缓存(对比缓存)
强制缓存失效后,浏览器携带会带着缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要应用于一些时常需要动态更新的资源文件。
1. Last-Modified和If-Modified-Since
首先,浏览器第一次向服务器请求一个资源,服务器在返回这个资源的同时,在respone的header加上Last-Modified字段,表示该资源在服务器上的最后修改时间;
然后,浏览器再次向服务器请求这个资源时,在request的header上加上If-Modified-Since字段,这个值就是上一次请求时返回的Last-Modified的值;
最后,服务器收到资源请求时,会比较If-Modified-Since字段值和被请求资源的最后修改时间,若资源最后修改时间较旧,则说明文件没有修改,返回304 Not Modified, 浏览器从缓存中加载资源;若不相同,说明文件被更新,浏览器直接从服务器加载资源, 并返回状态码200;
加载资源时同时更新Reponse Header的Last-Modified。
首先,浏览器第一次向服务器请求一个资源,服务器在返回这个资源的同时,在respone的header加上ETag(生成规则由服务器决定,例如,Apache中,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的)字段;
然后,浏览器再次跟服务器请求这个资源时,在request的header上加上If-None-Match,这个值就是上一次请求时返回的ETag的值;
最后, 服务器再次收到资源请求时,再根据资源生成一个新的ETag,与浏览器传过来If-None-Match比较,如果这两个值相同,则说明资源没有变化,返回304 Not Modified, 浏览器从缓存中加载资源,否则从服务器加载资源, 并返回状态码200。与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化。
有了Last-Modified,还要用Etag呢?
1. 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
2. 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
对于上述情景,利用ETag能够更加准确的控制缓存,因为ETag是服务器自动生成的资源在服务器端的唯一标识符,资源每次变动,都会生成新的ETag值。Last-Modified与ETag是可以一起使用的,但服务器会优先验证ETag。
基于以上,来总结一下:
首先先看下用户行为对缓存的影响,见下图:
整个的浏览器的一个强缓存和协商缓存结合使用的可以用下图表示:
以上是关于浏览器缓存策略回顾的主要内容,如果未能解决你的问题,请参考以下文章
理论 + 实践来通学习浏览器缓存策略
浏览器缓存策略
浏览器缓存策略
浏览器缓存机制剖析
浏览器的缓存策略
HTTP 缓存策略