浏览器缓存机制
非HTTP协议定义的缓存机制
<meta http-equiv="Pragma" content="no-cache"> //告诉浏览器当前页面不被缓存
与缓存有关的HTTP头信息
请求、响应都有的头部
Cache-control:
no-cache 告诉浏览器忽略资源的缓存副本,强制每次请求直接发送给服务器,拉取资源,但不是“不缓存”
no-store 强制缓存在任何情况下都不要保留任何副本
max-age=秒 指明缓存副本的有效时长,从请求时间开始到过期时间之间的秒数
public 任何路径的缓存者(本地缓存、代理服务器),可以无条件的缓存该资源
private 只针对单个用户或者实体(不同用户、窗口)缓存资源
响应头信息
Pragma:no-cache
告诉浏览器忽略资源的缓存副本,每次访问都需要去服务器拉取。【http1.0中存在的字段,在http1.1已被抛弃,使用cache-control
替代,但为了做到http向下兼容,很多网站依旧会带上这个字段】
Expries:时间
启用缓存和定义缓存失效时间。告诉浏览器缓存资源过期时间,如果还没过该时间则不发请求。【http1.0中的字段,是相对于服务器上
的时间而言的,如果客户端与服务器时间不一致,那就没意义了。HTTP1.1开始,使用cache-control:max-age=秒替代】
Last-Modified:时间
告诉浏览器这个资源最后的修改时间。服务器将资源传递给客户端时,会将资源最后更改的时间以这个字段一起返回给客户端。
【只能精确到秒,如果某些文件在1秒之内被修改多次,将不能准确表示文件最后的修改时间】
ETag:唯一标识值
告诉浏览器当前资源在服务器的唯一标识符(生成规则由服务器决定)
请求头部
If-Modified-Since:时间(上次响应头的Last-Modified值)
值为上次响应头的Last-Modified值,再次向Web服务器请求时带上此头。【服务器收到请求后,将此时间与被请求资源的
最后修改时间进行比对。若最后时间较新,说明资源被改过,则响应整片资源内容(写在响应消息包体内),包括更新Last-Modified的值,
HTTP 200;若最后修改时间较旧,说明资源无更改,则响应HTTP 304(无需包体,节省浏览),告知浏览器继续使用所保存的cache】
If-None-Match:ETag值
当资源过期时(使用Cache-Control标识的max-age),发现资源具有ETag声明,则再次向web服务器请求时带上此头。web服务器收到请求后,
将此值与被请求资源的ETag进行比较,如果相同,就将If-None-Match的值设为false,返回状态为304,客户端继续使用本地缓存。客户端继续使用本地缓存决定返回200或304。
Last-Modified 和 If-Modified-Since
Last-Modified 表示本地文件最后修改日期,If-Modified-Since 会将 Last-Modified 的值发送给服务器,询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来。
但是如果在本地打开缓存文件,就会造成 Last-Modified 被修改,所以在 HTTP / 1.1 出现了 ETag 。
ETag 和 If-None-Match
ETag 类似于文件指纹,If-None-Match 会将当前 ETag 发送给服务器,询问该资源 ETag 是否变动,有变动的话就将新的资源发送回来。并且 ETag 优先级比 Last-Modified 高。
# 选择合适的缓存策略
Cache-Control与Expires的比较
Cache-Control与Expires同时设置,则Cache-Control优先级更高。
Last-modified/ETag 与Cache-Control/Expires的比较
配置Last-modified/ETag的情况下,浏览器再次访问统一URI的资源,还是会发送请求到服务器询问文件是否已经修改,如果没有,返回304,
告知浏览器直接使用本地的缓存;如果修改过,那就整个数据重新发给浏览器。
Cache-Control/Expires则不同,如果检测到本地的缓存还在有效时间内,浏览器直接使用缓存副本, 不会发送任何请求。
两者一起使用时,Cache-Control/Expires的优先级要高于Last-modified/ETag。即当本地副本根据Cache-Control/Expires发现还在有
效期内,则不会再次发送请求去服务器询问修改时间(Last-modified)或实体标识(ETag)了。
一般情况下,使用Cache-Control/Expires会配合Last-modified/ETag一起使用,因为即使服务器设置缓存时间,当用户点击“刷新”按钮时
,浏览器会忽略缓存继续向服务器发送请求,这时Last-Modified/ETag将能够很好利用304,从而减少响应开销。
Last-modified 与 ETag的比较
Last-modified的几个问题:
-
1.Last-modified的时间只能精确到秒,如果某些文件在1秒之内被修改多次,他将不能准确表示文件新鲜度。
-
2.如果某些文件会被定期生成,但内容并没有变化,但是Last-modified却改变了,这样会导致缓存无法使用。
-
3.有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形。
ETag能够更加准确的控制缓存。
一起使用的时候,服务器会优先验证ETag,一致的情况下,再继续比对Last-modified,最后才决定是否返回304。
Last-Modified/If-Modified-Since,ETag/If-None-Match都要配合cache-control使用。
不能缓存的请求
-
1.HTTP头中无Cache-Control:no-cache,pragma:no-chache,或Cache-Control:max-age=0
-
2.需要根据Cookie、认证信息等决定输入内容的动态请求是不能被缓存的。
-
3.经过HTTPS安全加密的请求。
-
4.POST请求不能缓存。
-
5.HTTP响应头中不包含Last-Modified/ETag,也不包含Cache-Cntrol/Expires的请求无法被缓存。
用户行为与缓存
F5刷新:Expires/Cache-control过期时间会失效,但是Last-modified/ETag有效
ctrl + F5 /r 刷新:都无效,强制从服务器下载文件,响应200。
浏览器HTTP请求流程:
第一次请求:
再次请求:
是否过期:根据cache-control和Expires判断(cache-control优先)
==========================2018-07-02 新增==========
强制缓存与对比缓存
强制缓存
强制缓存:在缓存数据未失效的情况下,可以直接使用缓存数据。
对于强制缓存来说,响应header终会有两个字段来表明失效规则(expires【http1.0基本不再使用】/cache-control【http1.1】)
- cache-control:
默认private //客户端可以缓存
max-age:xxx; //缓存内容将在xxx秒后失效
no-cache:需要使用对比缓存来验证缓存数据
对比缓存
需要进行比较来判断是否可以使用缓存
浏览器第一次请求数据时,服务器会将缓存标识与数据一起返回给客户端,客户端将二者备份至缓存数据库中。再次请求时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识来判断,判断成功后返回304响应(not modified),通知客户端比较成功,可以使用缓存数据。
ETag:存放缓存标识和If-Node-Match:ETag //再次请求时进行比较缓存标识
优先级高于
Last-Modified和If-Modified-Since
### 对于强制缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求直接使用缓存。不在时间内,执行比较缓存策略。
对于比较缓存,将缓存信息中的ETag和Last-modified通过请求发送给服务器,由服务器校验,返回304时,浏览器直接使用缓存。