zoukankan      html  css  js  c++  java
  • Chrome或Firefox浏览器缓存时间问题

    1、浏览器默认缓存时间

      firefox 的缓存时间时长

      (访问时间 - 最后修改时间) ÷  10

      例子:

      假设 7点0分 访问的 5点0分修改的 index.html ,

      那么缓存时间为

      2*60*60 ÷ 10 = 720 秒

      页面缓存时间为 720 秒

    2、设置页面禁止缓存

    1.  
      <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
    2.  
      <meta http-equiv="Pragma" content="no-cache" />
    3.  
      <meta http-equiv="Expires" content="0" />

      

      no-cache : 协商缓存

      no-store : 不缓存

      must-revalidate : 过期强制请求服务器

    先放上结论吧,Chrome和Firefox对js、css之类的文件,在内存中的缓存时长,是:
    (访问时间 - 该文件的最后修改时间) ÷ 10

    假设文件 a.js 最后编辑时间是 2018年12月1号 10点0分0秒;
    Chrome的第一次访问时间是 2018年12月1号 12点0分0秒;
    第一次访问与文件编辑时间相差2小时,即7200秒,那么缓存时长就是720秒
    即结论如下:
    1、在 2018年12月1号 12点0分1秒到 12点11分59秒,这12分钟内,浏览器不会发起http请求;
    2、在 2018年12月1号 12点12分0秒,会发起带 If-Modified-Since 的http请求
    3、如果希望浏览器每次都发起http请求,请在WebServer返回Header Cache-Control: no-cache

    问题的由来:
    我提供了一个多语言的js资源包服务,昨天有QA反馈,后台修改了内容,前台没变化!!
    PC上还好办,可以按Ctrl + F5,强制刷新,手机上就不好办了,只能等着缓存过期。
    而且我们也不可能主动通知用户去强制刷新吧!

    问题解决很简单,在IIS的站点=》HTTP响应标头里,添加一个Header:Cache-Control,值为no-cache,
    问题解决。
    注意:加了这个标头后,浏览器在请求这个站点的js/css/图片资源时,每次都会重新发起HTTP连接请求,虽然请求的Header里会带上 If-Modified-Since,但是HTTP连接本身也是很耗资源的,所以要根据场景来选择性添加,
    比如不添加标头,而是通过js加版本号来避免缓存。

    虽然缓存问题解决了,但是如果没加标头,Chrome会在内存缓存多久啊?这个问题我搜索了一下,没有找到Chrome的资料,但是有文章说Firefox是按顶部的结论实现的,参考RFC协议关于缓存过期的部分:
    https://tools.ietf.org/html/rfc2616#section-13.2.4

    为了验证,写了一个html定时刷新自己,然后扔在IIS站点下,然后用Chrome的F12->Network抓包:

    <!DOCTYPE html>
    <html>
    <head>
    <script type="text/javascript" src="jq_125bece.js"></script>
    <script type="text/javascript" src="errnew.js"></script>
    <link rel="stylesheet" href="a.css"/>
    <script type="text/javascript">
    $(document).ready(function() {
    setTimeout(function(){
    location.href = 'a.html?' + Date.now();
    }, 10000);
    });
    </script>
    </head>
    <body>
    </body>
    </html>

    验证的结果,Chrome也是按这个机制作为本地缓存过期策略。

    文章最后,贴一段C#版本的判断304响应的代码,用于客户端更新本地资源:

    static void Main(string[] args)
    {
    var url = "https://beinet.cn/language.js";
    var localFile = @"d:language.js";

    var ret = UpdateResource(url, localFile);
    Console.WriteLine("是否有更新" + ret);

    ret = UpdateResource(url, localFile);
    Console.WriteLine("是否有更新" + ret);
    Console.Read();
    }


    /// <summary>
    /// 更新本地资源文件,并返回是否进行了更新
    /// </summary>
    /// <param name="url">远程资源文件地址</param>
    /// <param name="localFile">本地缓存资源地址</param>
    /// <returns></returns>
    static bool UpdateResource(string url, string localFile)
    {
    const string responseHeader = "Last-Modified";
    var timeFile = localFile + responseHeader;
    string lastModified = null;
    if (File.Exists(timeFile))
    {
    lastModified = File.ReadAllText(timeFile);
    }

    var request = (HttpWebRequest)WebRequest.Create(url);
    request.Headers.Add("Accept-Encoding", "gzip, deflate");
    request.Timeout = 5000; // 默认5秒超时
    request.AllowAutoRedirect = true;
    if (!string.IsNullOrEmpty(lastModified))
    {
    request.IfModifiedSince = DateTime.Parse(lastModified); // 设置Header if-modified-since
    }
    string json;
    HttpWebResponse response;
    try
    {
    response = (HttpWebResponse) request.GetResponse();
    }
    catch (WebException exp)
    {
    if(exp.Response != null && ((HttpWebResponse)exp.Response).StatusCode == HttpStatusCode.NotModified)
    return false;
    throw;
    }
    using (response)
    {
    lastModified = response.Headers[responseHeader];
    json = GetResponseString(response, Encoding.UTF8);
    }
    // todo: 这里要考虑判断是否json格式
    SaveToFile(localFile, json);
    SaveToFile(timeFile, lastModified);
    return true;
    }

    /// <summary>
    /// 从HttpResposne中获取响应字符串
    /// </summary>
    /// <param name="response"></param>
    /// <param name="encoding"></param>
    /// <returns></returns>
    static string GetResponseString(HttpWebResponse response, Encoding encoding)
    {
    using (Stream stream = response.GetResponseStream())
    {
    if (stream == null)
    {
    return "GetResponseStream is null";
    }
    string str;
    string contentEncoding = response.ContentEncoding.ToLower();
    if (contentEncoding.Contains("gzip"))
    {
    using (Stream stream2 = new GZipStream(stream, CompressionMode.Decompress))
    {
    str = GetFromStream(stream2, encoding);
    }
    }
    else if (contentEncoding.Contains("deflate"))
    {
    using (Stream stream2 = new DeflateStream(stream, CompressionMode.Decompress))
    {
    str = GetFromStream(stream2, encoding);
    }
    }
    else
    {
    str = GetFromStream(stream, encoding);
    }
    return str;
    }
    }

    static string GetFromStream(Stream stream, Encoding encoding)
    {
    using (StreamReader reader = new StreamReader(stream, encoding))
    {
    return reader.ReadToEnd();
    }
    }

    static void SaveToFile(string targetFile, string content)
    {
    var now = DateTime.Now.ToString("yyyyMMddHHmmssfffffff");
    // 写入临时文件,再进行移动
    var tmpFile = targetFile + now;
    File.WriteAllText(tmpFile, content);

    if (File.Exists(targetFile))
    {
    var bakFile = targetFile + "bak" + now; // 备份文件
    File.Move(targetFile, bakFile);
    }
    File.Move(tmpFile, targetFile);
    }

    我们只需要努力,然后剩下的交给时间。
  • 相关阅读:
    js正则表达式中的问号使用技巧总结
    380. Insert Delete GetRandom O(1)
    34. Find First and Last Position of Element in Sorted Array
    162. Find Peak Element
    220. Contains Duplicate III
    269. Alien Dictionary
    18. 4Sum
    15. 3Sum
    224. Basic Calculator
    227. Basic Calculator II
  • 原文地址:https://www.cnblogs.com/lgj8/p/14955108.html
Copyright © 2011-2022 走看看