当前位置: 代码迷 >> 综合 >> 浏览器 缓存 面试 参数解析 Cache-Control Expires ETag Last-Modified
  详细解决方案

浏览器 缓存 面试 参数解析 Cache-Control Expires ETag Last-Modified

热度:66   发布时间:2023-10-30 21:31:50.0

面试说法

面试:
缓存主要分为强缓存和协议缓存,在浏览器加载资源的时候,会根据请求头判断是否命中强缓存,如果命中强缓存的话,会直接从缓存中读取数据而不发送请求。
判断强缓存的方式的话,需要判断请求头中是否有cache-control或者expires字段,这两个字段分别规定了以秒为单位的生存时长,和gmt格式的过期日期,如果在缓存未过期的时间内,就能命中强缓存,优先级的话是cache-control优先于expires
如果没有命中强缓存就要看看是否命中协议缓存,协议缓存需要两组请求头并通过服务器进行校验,如果命中协议缓存都话,就会返回304,否则就返回请求的资源。判断是否命中协议缓存需要用两组请求头来判断,第一次向服务器发送请求,服务器返回字段中会包含ETag或者Last-Modified,再次发起请求的时候,如果强缓存已经过期,并且资源中ETag和Last-modified声明,就会在请求中带上对应的 If-none-match和if-modified-since字段
如果是Etag,第二次请求就会带if-none-match,他的值就是etag的值,服务器收到后发现如果有if-none-match字段,就个服务器端的相应校验串进行对比,没有更改就返回304
如果是last-modified。第二次请求就会带上if-modified-since,他的值就是last-modified的值,服务器将该值与被请求资源的最后修改时间进行对比,如果服务器 的资源的最后修改时间比较新,说明被修改过,就返回200和新资源,如果一致说明没有修改过,返回304

详细介绍

1. 缓存作用及备注

作用

  • 减少用户等待时间,提升用户体验
  • 减少带宽,降低网络负荷

备注

  • 强缓存不会发生请求,协商缓存发请求
  • F5刷新和新开窗口会跳过强缓存
  • Ctrl+F5 强制刷新会跳过强缓存和协议缓存

缓存流程图

在这里插入图片描述

2. 执行顺序

  • Cache-Control > Expires > ETag > Last-Modified

3. 分类

① 强缓存

过程
浏览器加载资源时,会根据请求的header头部判断是否命中强缓存,如果命中直接从缓存中读取数据而不发送请求,200(from cache)

命中规则:
如果请求头中有cache-control(1.1)或者expires(1.0)字段,分别规定了生存时长(以秒为单位)和绝对过期日期(GMT时间格式),如果请求在缓存未过期内,则能命中缓存

② 协议缓存

过程:
通过两组请求头,服务器进行校验,如果命中协议缓存,返回304,否则返回新资源以及200
命中规则:
用两组请求头来判断,
① 第一次向服务器发送请求,服务器返回字段中包含ETag和Last-Modified。、
② 再次发起请求时,如果Cache-Control缓存过期,并且资源有ETag和Last-Modified声明,则带上分别对应的If-None-Match和If-Modified-Since

  • 如果是ETag: 第二次请求头带上If-None-Match,值就是ETag,服务器收到请求后发现有If-None-Match字段,就和服务器端的相应校验串对比,决定返回304还是200
  • 如果是Last-Modified: 第二次请求头带上If-Modified-Since,值就是Last-Modified,服务器收到请求后发现有If-Modified-Since字段,则与被请求资源的最后修改时间进行对比。如果服务器的资源最后修改时间比较新,说明又修改过,则响应200返回资源;如果一致说明并未修改,返回304使用缓存

4. 参数详解

① cache-control

用于强缓存,直接从缓存中取数而不向服务器发请求,有多个参数可以决定是否走缓存、缓存存活时间等
可缓存性:

  • public:http请求过程中,返回内容经过的任何路径(代理服务器、客户端浏览器等)都可以对数据进行缓存
  • private:只有发起请求的浏览器才可以缓存
  • no-cache:可以缓存,但是先向服务器确认返回的相应是否被更改,才能使用该响应
  • no-store:所有内容都不会被缓存到缓存或者Internet临时文件中

到期时间:

  • max-age= :最常用,缓存到期时间,以秒为单位,过期需要从服务器重新请求
  • max-stale=:请求方header中,机试缓存过期,在max-stale时间内还可以使用缓存(代理服务器中)
    可以重复设置,no-store的优先级最高

② expires

expires提供一个GMT格式的过期日期,在该日期之前都会使用缓存而非请求
如 Expires:Sun, 08 Nov 2009 03:37:26 GMT
注意:

  • cache-control的max-age和max-stale优先级高于expires,会将其覆盖
  • 使用expires会存在服务器和浏览器时间不一致的问题

expires是1.0的方法,现在大多使用1.1

③ ETag/If-None-match

ETag/If-None-match需要配合cache-control使用,当cache-concrol过期后,才使用ETag。
ETag: 资源在服务器的唯一标识(由服务器决定如何生成)。在Apache中,ETag的值默认是对文件的索引节(INode)、大小(size)和最后修改时间(MTime)进行hash得到的。可以从文件内容进行判断是否进行过更改
If-None-Match: 当缓存过期的时候,发现资源有ETag字段,则在请求头中带上If-None-Match,其值就是ETag的值,问问服务器资源有没有更改,服务器把请求里的If-None-Match值与资源在服务器的校验值进行对比,

  • 一致就没有更改返回304
  • 不一致说明有更改,返回200和新资源

④ Last-Modified/If-Modified-Since

Last-Modified/If-Modified-Since需要配合cache-control使用,当cache-concrol过期后,才使用Last-Modified。优先级低于Etag
last-modified: 资源最后修改时间
if-modified-since: 当cache-control过期后,发现资源有last-modified字段,就在请求中加入if-modified-since。其值是last-modified的值,服务器接到请求后对比最后修改时间,服务器端的比较新就说明有更改返回200和资源,一致说明未更改返回304

5、有last-modified为什么还用Etag

① last-modified只能精确到秒级,如果资源在一秒内多次修改,不能准确标注文件的修改时间
② 有些文件会定期生成,但是内容并没有发生变化,但是last-modified变了不能使用缓存
③ 可能存在服务器没有准确获取资源最后修改时间,或者与代理服务器时间不一致的情况

6、200ok(from cache)和304 Not Modified区别

200OK不向服务器发送请求,直接使用缓存
304 则是想服务器发请求咨询,服务器认为文件没有更改,不需要重新获取,使用浏览器的缓存即可

  • 200OK出现情景:
    ① 地址栏回车
    ② 页面链接跳转
    ③ 前进、后退

  • 304出现情景:
    ① F5刷新
    ② 新开窗口

7、清除缓存/无法缓存

清除缓存:
① meta标签中令cache-control为no-cache或者expires为0

//不缓存
<META HTTP-EQUIV="pragma" CONTENT="no-cache"> 
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate"> 
<META HTTP-EQUIV="expires" CONTENT="0">

② ajax请求清除
用ajax请求服务器最新文件,并加上请求头If-Modified-Since和Cache-Control

$.ajax({
    url:'www.haorooms.com',dataType:'json',data:{
    },beforeSend :function(xmlHttp){
     xmlHttp.setRequestHeader("If-Modified-Since","0"); xmlHttp.setRequestHeader("Cache-Control","no-cache");},success:function(response){
    //操作}async:false});

或者cache:false

 $.ajax({
    url:'www.haorooms.com',dataType:'json',data:{
    },cache:false, ifModified :true ,success:function(response){
    //操作}async:false});

不能缓存:
① http头中cache-control为no-cache或者为max-age: 0
② 需要根据cookie,和输入内容的动态请求
③ 经过https加密的请求
④ post请求不可以被缓存
⑤ http响应头中不含Last-Modified/Etag,也不包含Cache-Control/Expires的请求无法被缓存

  相关解决方案