先放上结论吧,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); }
关于页面缓存的Cache-Control之no-store
附网上解释:
Cache-Control
Http1.1 中的标准,可以看成是 expires 的补充。使用的是相对时间的概念。
简单介绍下Cache-Control的属性设置。
1)max-age: 设置缓存的最大的有效时间,单位为秒(s)。max-age会覆盖掉Expires
2) s-maxage: 只用于共享缓存,比如CDN缓存(s -> share)。与max-age 的区别是:max-age用于普通缓存,
而s-maxage用于代理缓存。如果存在s-maxage,则会覆盖max-age 和 Expires.
3) public:响应会被缓存,并且在多用户间共享。默认是public。
4) private: 响应只作为私有的缓存,不能在用户间共享。如果要求HTTP认证,响应会自动设置为private。
5)no-cache: 指定不缓存响应,表明资源不进行缓存。但是设置了no-cache之后并不代表浏览器不缓存,而是在缓存前要向服务器确认资源是否被更改。因此有的时候只设置no-cache防止缓存还是不够保险,还可以加上private指令,将过期时间设为过去的时间。
6)no-store: 绝对禁止缓存。
7)must-revalidate: 如果页面过期,则去服务器进行获取。
参考浏览器缓存策略:
https://blog.csdn.net/yongche_shi/article/details/51866634
相关推荐
同时修改广告代码之后如果没有变化,清空一下浏览器缓存再刷新即可,一般360浏览器、遨游浏览器都是ie核心,firefox、chrome都是独立核心清空缓存的位置都在浏览器自身的设置里面。 后台地址:http://网站首页/...
使用JSer,您几乎无需再考虑各浏览器的兼容问题,目前JSer兼容的浏览器核心: IE, Firefox, Opera, Chrome, safari。 通过JSer,您可以便捷的使用DOM操作、CSS样式访问、属性读写、事件绑定、行为切换、动态载入、...
后台 chrome/firefox/ie9 github地址:https://github.com/dongfangshangren/Zblog。 示例见:http://blog.zhouhaocheng.cn/。注:前台界面部分借鉴自Flat和并发编程网。 标签:Zblog
wordpress主题不依赖任何前端框架,支持13种颜色风格、CSS3+HTML5、扁平化、响应式设计,兼容360、百度、Firefox、Chrome等主流浏览器及大部分移动浏览器。 集成多种小工具:最新文章、本站推荐、热评文章、热门文章...
使用JSer,您几乎无需再考虑各浏览器的兼容问题,目前JSer兼容的浏览器核心: IE, Firefox, Opera, Chrome, safari。 通过JSer,您可以便捷的使用DOM操作、CSS样式访问、属性读写、事件绑定、行为切换、动态载入、...
1、重新改写模板使之能兼容360浏览器、360极速浏览器、火狐浏览器、Google Chrome等主流浏览器 2、删除在线人数状态,删除公告、删除图片友情链接、使论坛更加简约 3、更改论坛为主流字体:微软雅黑
注意:DIY时浏览器请尽量选用谷歌chrome或Mozilla Firefox,这样不容易出问题!!!! 重要提示:以下“导入”前,请先点一下“清空”,避免出问题; 4. 在门户首页, 点右上角的 [DIY] 导入 “门户首页_导入.xml” 这...
要求: JDK 8 (使用Gradle包装器) 兼容浏览器(当前为Chrome / Chrome(Android)/ Firefox / Opera)跑步./gradlew build./gradlew run细节这个简单的示例使用Service Worker来预先加载和缓存静态资源以及主页。...
模板采用DIV CSS布局,并兼容 IE6/7/8/9/10、Google Chrome、Firefox、Opera、Webkit、搜狗、360、遨游等浏览器。 4)内置SEO功能 提升网站搜索引擎排名 SEO功能包含页面标题、关键词、描述设置;搜索引擎提交;...
采用ASP ACCESS语言环境(其他版本将陆续推出),DIV CSS构架及APPLICATION缓存技术,代码简洁标准,全面兼容IE6、IE7、IE8、IE9、Firefox、Firefox、Chrome、Safari等等主流浏览器。 米号文章管理系统功能 首页静态...
采用ASP ACCESS语言环境(其他版本将陆续推出),DIV CSS构架及APPLICATION缓存技术,代码简洁标准,全面兼容IE6、IE7、IE8、IE9、Firefox、Firefox、Chrome、Safari等等主流浏览器。 首页静态生成;全站模板标签...
采用ASP+ACCESS语言环境(其他版本将陆续推出),DIV+CSS构架及APPLICATION缓存技术,代码简洁标准,全面兼容IE6、IE7、IE8、IE9、Firefox、Firefox、Chrome、Safari等等主流浏览器。米号文章管理系统功能首页静态...
模板采用DIV+CSS布局,并兼容 IE6/7/8/9/10、Google Chrome、Firefox、Opera、Webkit、搜狗、360、遨游等浏览器。 4)内置SEO功能 提升网站搜索引擎排名 SEO功能包含页面标题、关键词、描述设置;搜索引擎提交;...
米号文章管理系统采用ASP ACCESS语言环境(其他版本将陆续推出),DIV CSS构架及APPLICATION缓存技术,代码简洁标准,全面兼容IE6、IE7、IE8、IE9、Firefox、Firefox、Chrome、Safari等等主流浏览器。 功能特点:...
完美兼容IE7+、Firefox、Chrome、360浏览器等、主流浏览器。 页面简洁简单,容易管理,DEDE内核都可以使用,附带测试数据。 源码特点: 1、网站手工DIV+css,代码精简,首页排版整洁大方、布局合理、利于SEO、...
模板采用DIV CSS布局,并兼容 IE6/7/8/9/10、Google Chrome、Firefox、Opera、Webkit、搜狗、360、遨游等浏览器。 4)内置SEO功能 提升网站搜索引擎排名 SEO功能包含页面标题、关键词、描述设置;搜索引擎提交;...
1、重新改写模板使之能兼容360浏览器、360极速浏览器、火狐浏览器、Google Chrome等主流浏览器2、删除在线人数状态,删除公告、删除图片友情链接、使论坛更加简约3、更改论坛为主流字体:微软雅黑
完美兼容IE7+、Firefox、Chrome、360浏览器等、主流浏览器。 页面简洁简单,容易管理,DEDE内核都可以使用,附带测试数据。 源码特点: 1、网站手工DIV+css,代码精简,首页排版整洁大方、布局合理、利于SEO、...
2.[纠正]纠正后台如果是用chrome核心浏览器,会造成底部一大截空白的BUG 3.[纠正]纠正部分浏览器后台导航菜单间间隔背景图会重复显示多次BUG 4.[纠正]纠正前台导航下拉二级菜单多次经过会出现重复伸缩问题 5.[纠正]...
完美兼容IE7+、Firefox、Chrome、360浏览器等、主流浏览器。 页面简洁简单,容易管理,DEDE内核都可以使用,附带测试数据。 源码特点: 1、网站手工DIV+css,代码精简,首页排版整洁大方、布局合理、利于SEO、...