客户端缓存脚本通常让我们又爱又恨,爱他,是因为他确实可以有效防止相同的文件在客户端和服务器之间传来传去,恨他,是因为当你真的需要更新他的时候,他可能不理会你的要求。

  • 客户端解决办法

很多人直接在脚本后面加一个时间戳作为参数,当我们每次去获取网页的时候,都会在后面去增加一个时间戳,这样脚本文件就会每次都回传给浏览器,具体表现为你每次F5刷新页面(不是CTRL+F5)的时候,返回状态码始终都是200。

当然,这么残暴地写,在一些企业内网的环境,也没什么大不了,但是还是很多人会有点儿洁癖。其实只要在每次变更的时候强制大家刷新一下,不是就可以了吗?于是大家认为在后面加一个版本号,如v=2之类的,这样只需要每次更新脚本后,在引用的页面,更新这个v,就可以让客户端更新脚本了。

在这里,推荐大家用IE的F12开发者工具来抓网络包,当然Fiddler等也都可以,不过确实在这件事上,一个是没必要,一个可能Fiddler在修改IE端口指向8000之后可能会有问题。

回到话题,这里需要解释一下浏览器对客户端缓存看的是整条URL包括后面的参数,所以当你有个地方引用:

http://volnet.cnblogs.com/scripts/demo.js 的时候,你再次访问

http://volnet.cnblogs.com/scripts/demo.js?v=2 的时候,该缓存仍然在你的浏览器里呆着,当你下次继续访问不带参数的demo.js的时候,你引用的仍然还是旧的文件。

你可能对此表示不以为然,因为大部分的脚本通常都是你自己在引用,因此你更新他们的时候,总是很容易。但是有的时候,你的脚本会被第三方引用,当你变更脚本的时候,你希望他们尽量少去改动,这时候,你可能就会遇到客户端无法刷新脚本的问题。

这时候你可能会想到Last-Modified和ETag标签,这些标签的出现,既可以替代在js文件后面加版本号或者时间戳的问题,在服务器修改他们后,通常可以被监测到,并修改服务器的ETag值,当下次从客户浏览器传回If-None-Match和If-Modified-Since的时候就可以在服务器判断是应该返回304呢,还是返回200呢?看上去挺美好的事情,经常会有各种各样的意想不到。谁知道这些看上去很简单的东西,并不是每个浏览器都具备的能力,而且可能的原因还来自各种各样千奇百怪的客户端设置,抛开他们的问题而言。摆在眼前的事实就是,客户端的脚本就是因为304而不更新了,你能怎么办?你抓回来的包,可以证明你的服务器下发了ETag,但人家就是不给你返回If-None-Match,你也不太可能在服务器去修改脚本的版本号,难道你要让大家都按Ctrl+F5么?(可怜的事情还真不是发生在一些过时的浏览器上,今天找到的几个问题,IE9/IE8全都遇上了)。

这里有个问题需要说一下,就是当你的文件已经是304的时候,除非服务器支持ETag并且你的客户端带回If-None-Match标记,或者是Last-Modified和If-Modifed-Since组合的时候,原来那个链接,基本上都不会给你返回200,这或许是你早期的服务器设置所造成的,他不会因为你重新下发ETag,而让他们去给你返回这些值,除非你这次是200,并同时下发了那些用来缓存的标记。这个结论是我推导出来的,可能是IE9的行为bug,或者时设计使然。

我们如何避免他们呢?

  • 服务端解决办法

我想来想去,既然服务器在我手里,我可以控制,并且它确实下发了ETag,那么我何不就借服务器的能力,让它把状态200发下去呢?激发它下发状态200,就是让它回传一个不一样的ETag值(在客户端叫If-None-Match),这样服务器自然就会下发了,而那些一直缓存不更新的客户,通常是因为没有带任何与之相关的参数,而宣布刷新资源失败。这里我用了XMLHttpRequest去发一个GET请求,并把驱动状态码200的必要条件给带上,就可以了。

var httpCacheUtil = {createXHR: function () {if (typeof XMLHttpRequest != "undefined") {return new XMLHttpRequest();} else if (typeof ActiveXObject != "undefined") {if (typeof arguments.callee.activeXString != "string") {var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"];for (var i = 0, len = versions.length; i < len; ++i) {try {var xhr = new ActiveXObject(versions[i]);arguments.callee.activeXString = versions[i];return xhr;}  catch (ex) {// pass}}}return new ActiveXObject(arguments.callee.activeXString);
} else {throw new Error("No XHR object available");
}
},update: function(url){try {var success = function(responseText) {};var error = function(errorStatus) {};var xhr = httpCacheUtil.createXHR();if(typeof xhr != "undefined" && xhr != null) {xhr.onreadystatechange = function (event) {if (xhr.readyState == 4) {if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {if (typeof success === "function")   success(xhr.responseText);} else {if (typeof error === "function")error(xhr.status);}}};xhr.open("GET", url, false);xhr.setRequestHeader("If-None-Match","\"22426f327b8cd1:0\"");xhr.setRequestHeader("If-Modified-Since", "Sat, 31 Dec 2011 02:51:00 GMT");xhr.send(null);}}catch(e){// throw no exception}}};httpCacheUtil.update("http://volnet.cnblogs.com/Scripts/demo1.js");httpCacheUtil.update("http://volnet.cnblogs.com/Scripts/demo2.js");

那些关于ETag和Last-Modifed,Cache-Control:no-cache等的说明文档,在网上已经很多了,大家可以参考相关资料来了解浏览器缓存的相关知识。

转:
http://www.cnblogs.com/volnet/archive/2012/11/02/2752019.html

如何直接强制客户端刷新.js文件相关推荐

  1. java页面强制刷新,JS关于刷新页面的相关总结

    很多程序员无论是新手还是老的程序员都避免不了关于JS刷新页面的相关内容,在本文中我们整理了脚本之家总结的关于JS页面刷新的相关重要知识点文章,一起来跟着学习下. reload 方法,该方法强迫浏览器刷 ...

  2. 拆分js文件_2021入门Webpack,看这篇就够了:Webpack.config.js 解析

    这是优妈成长记的第63篇原创 这是一个webpack配置说明 本文是发布在github上webpack-demo的README文件内容.主要对webpack.config.js每一条的注释说明. gi ...

  3. 【JS】问题——解决JS文件页面更新不生效问题

    解决JS文件页面更新不生效问题 问题产生 昨天在本地测试一个web项目,启动后页面某个按钮点击没反应,通过浏览器控制台,追了追代码发现js写法不支持,就顺手把js文件给改了.然后重新发布,点击按钮发现 ...

  4. 项目js文件修改后浏览器不能及时更新的解决办法

    在做web开发过程中,经常需要调试js代码,而在这个时候我们修改过的代码可能不能生效.这是因为浏览器默认是有缓存的,但是这个时候缓存就会影响我们的调试工作,在这里就介绍一下chrome浏览器解决该问题 ...

  5. php js页面刷新,JS刷新页面方法总结

    这次给大家带来JS刷新页面方法总结,JS刷新页面的注意事项有哪些,下面就是实战案例,一起来看一下. JS刷新当前页面的几种方法总结reload 方法,该方法强迫浏览器刷新当前页面 replace 方法 ...

  6. fileinput.js php,JS文件上传神器bootstrap fileinput的解析

    这篇文章主要介绍了JS文件上传神器Bootstrap FileInput,样式非常美观,并且支持上传文件预览,ajax同步或异步上传,拖曳文件上传等炫酷的功能,具有一定的参考价值,感兴趣的小伙伴们可以 ...

  7. 仿163网盘无刷新多文件上传系统

    这个仿163网盘无刷新多文件上传系统,并没有用使用.net的控件,完全的手工制作.前台基本上是静态的,跟后台没有关系,所以后台用什么语言做都可以(后面有各个版本的实例下载). 本来觉得这个系统会很复杂 ...

  8. js加载html的head偶尔失效,外部 js 文件偶尔会加载失败

    最近有一个很奇怪的问题一直困扰着我: html 页面中,head部分引入了几个外部js文件. 比如: // 目前页面结构就是这样,其他的代码都和此异常无关,就不多贴了. // 这里就直接报错,显示 V ...

  9. 自己编写jQuery动态引入js文件插件 (jquery.import.dynamic.script)

    这个插件主要是结合jquery或者xhr异步请求来使用的,它可以把已经引入过的js文件记录在浏览器内存中,当下次再引入相同的文件就忽略该文件的引入. 当你用$.load("dir/my-pa ...

最新文章

  1. 某程序员发现新来女同事简历造假!原来是培训机构出身!纠结怎么处理,网友评论亮了!...
  2. 波士顿动力的仓库机器人Strentch来了,挑战每小时搬运800个箱子
  3. SqlServer一些用法
  4. html应用多个类,html – 如何避免重复多个css类
  5. js与android webview交互
  6. 两数相加c++_LeetCode 热题 HOT 100(01,两数相加)
  7. java excel 插件开发工具_程序员常用的15 种开发者工具推荐
  8. 在开发时选择静态方法还是非静态方法
  9. treeset java api_JAVAAPI学习值TreeSet类
  10. 51/STC12单片机SCON,PCON,TMOD寄存器定义及功能
  11. 谷歌地图坐标转换为百度地图坐标
  12. 解决——完美解决Anaconda打开Spyder5报错:link image0 hasn’t been detected!
  13. MyBatis--逆向工程
  14. JavaScript blog式日历控件
  15. Java 线上问题排查思路与工具使用
  16. Markdown设置字体大小、颜色、类型、加粗
  17. 【计算机网络】Linux环境中的TCP网络编程
  18. github大文件上传:使用LFS (以及如何将lfs从仓库中移除!)
  19. 【工作日记】这一年来完全用Linux工作的感受
  20. Labelme标注的json数据转化为coco格式的数据

热门文章

  1. V神:区块链跨链技术大规模应用将在一到两年内爆发
  2. 20165306 第八周学习任务
  3. MySql详解(六)
  4. 在Shell中使用alias
  5. wordpress的手动更新
  6. 【BootStrap】初步教程
  7. c语言开发 .c .h,求助C语言大佬 , 只会写到一个.c文件里 ,不会用.h头文件
  8. 中北大学c语言程序设计期末_中北大学:工作室联合育人 家校情温暖寒冬
  9. [蓝桥杯][算法提高VIP]盾神与积木游戏(贪心)
  10. 热狗树 树形dp(中国石油大学我要变强第九场)