我如何强制客户端刷新JavaScript文件?

目前我们正在进行一个私人testing版,所以仍然处于相当快速的变化过程中,虽然显然随着使用量的增加,我们将放慢这个过程。 这就是说,我们遇到的一个问题是,当我们推出新的JavaScript文件的更新后,客户端浏览器仍然使用caching版本的文件,他们没有看到更新。 显然,在支持电话上,我们可以简单地通知他们做一个Ctrl F5刷新,以确保他们从服务器获得最新的文件,但是最好在这个时间之前处理。

我们目前的想法是简单地将一个版本号附加到JavaScript文件的名称上,然后进行更改时,在脚本上增加版本并更新所有引用。 这绝对可以完成工作,但更新每个版本的参考可能会很麻烦。

我敢肯定,我们不是第一个处理这个问题的人,我想我会把它扔给社区。 你如何确保客户更新你的代码时更新他们的caching? 如果您使用上述方法,您是否正在使用简化更改的stream程?

据我所知,一个常见的解决scheme是在脚本的src链接中添加一个?<version>

例如:

 <script type="text/javascript" src="myfile.js?1500"></script> 

我认为在这一点上,没有比find-replace更好的方法来在所有脚本标记中增加这些“版本号”?

你可能有一个版本控制系统为你做? 例如,大多数版本控制系统都有办法在检入时自动注入修订号。

它看起来像这样:

 <script type="text/javascript" src="myfile.js?$$REVISION$$"></script> 

当然,总有这样的更好的解决scheme。

将当前时间附加到URL确实是一个常见的解决scheme。 但是,如果需要,也可以在Web服务器级别进行pipe理。 服务器可以configuration为发送不同的HTTP头文件。

例如,要强制文件被caching不超过1天,您可以发送:

 Cache-Control: max-age=86400, must-revalidate 

对于testing版,如果您想强制用户始终获取最新版本,则可以使用:

 Cache-Control: no-cache, must-revalidate 

Google Page-Speed:不要在静态资源的URL中包含查询string。 大多数代理,最明显的是通过3.0版本的squid,不会使用“?”来caching资源 即使在响应中存在Cache-control:public头部,它们的URL也是如此。 要为这些资源启用代理caching,请从对静态资源的引用中删除查询string,而将参数编码到文件名称本身中。

在这种情况下,您可以将该版本包含在以下url中: http ://abc.com/ v1.2 /script.js,并使用apache mod_rewrite将链接redirect到http://abc.com/script.js 。 当您更改版本时,客户端浏览器将更新新文件。

这个答案迟了6年,但是在很多地方我没有看到这个答案… HTML5引入了Application Cache来解决这个问题。 我发现我编写的新的服务器代码是存储在人们的浏览器中的旧JavaScript崩溃,所以我想find一种方法来过期他们的JavaScript。 使用如下所示的清单文件:

 CACHE MANIFEST # Aug 14, 2014 /mycode.js NETWORK: * 

并且每次您希望用户更新caching时都会用新的时间戳生成此文件。 作为一个方面说明,如果你添加这个,浏览器将不会重新加载(即使用户刷新页面),直到清单告诉它。

如何将文件大小添加为加载参数?

 <script type='text/javascript' src='path/to/file/mylibrary.js?filever=<?=filesize('path/to/file/mylibrary.js')?>'></script> 

所以每次更新文件时,“filever”参数都会改变。

如何更新文件和更新结果在相同的文件大小? 有什么可能?

并非所有浏览器都使用“?”来caching文件 在里面。 我做了什么来确保它被caching了,我把这个版本包含在文件名中。

所以,而不是stuff.js?123,我做stuff_123.js

我在apache中使用mod_redirect(我认为)有东西_ *。js去stuff.js

对于ASP.NET页面,我正在使用以下内容

之前

 <script src="/Scripts/pages/common.js" type="text/javascript"></script> 

后(强制重新加载)

 <script src="/Scripts/pages/common.js?ver<%=DateTime.Now.Ticks.ToString()%>" type="text/javascript"></script> 

添加DateTime.Now.Ticks工作得很好。

对于ASP.NET,我想下一个解决scheme具有高级选项(debugging/发布模式,版本):

通过这种方式包含的Js或Css文件:

 <script type="text/javascript" src="Scripts/exampleScript<%=Global.JsPostfix%>" /> <link rel="stylesheet" type="text/css" href="Css/exampleCss<%=Global.CssPostfix%>" /> 

Global.JsPostfix和Global.CssPostfix在Global.asax中按以下方式计算:

 protected void Application_Start(object sender, EventArgs e) { ... string jsVersion = ConfigurationManager.AppSettings["JsVersion"]; bool updateEveryAppStart = Convert.ToBoolean(ConfigurationManager.AppSettings["UpdateJsEveryAppStart"]); int buildNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision; JsPostfix = ""; #if !DEBUG JsPostfix += ".min"; #endif JsPostfix += ".js?" + jsVersion + "_" + buildNumber; if (updateEveryAppStart) { Random rand = new Random(); JsPosfix += "_" + rand.Next(); } ... } 

如果您生成的链接到JS文件的页面,一个简单的解决scheme是将文件的最后修改时间戳附加到生成的链接。

这与Huppie的答案非常相似,但是在没有关键字replace的版本控制系统中工作。 这也比追加当前时间好,因为即使文件没有改变,也会阻止caching。

jQuery函数getScript也可以用来确保每次加载页面时确实加载了一个js文件。

这是我做到的:

 $(document).ready(function(){ $.getScript("../data/playlist.js", function(data, textStatus, jqxhr){ startProgram(); }); }); 

http://api.jquery.com/jQuery.getScript/检查函数;

默认情况下,$ .getScript()将caching设置设置为false。 这会将时间戳查询参数附加到请求URL,以确保浏览器在每次请求时都下载脚本。

我的同事刚刚在http://www.stefanhayden.com/blog/2006/04/03/css-caching-hack/发布(参考css)之后发现了该方法的参考。; 很高兴看到别人正在使用它,它似乎工作。 我认为在这一点上,没有比find-replace更好的方法来在所有脚本标记中增加这些“版本号”?

尽pipe它是特定于框架的,但是Django 1.4具有与上述答案中的“greenfelt”站点的链接类似的function

PHP中

 function latest_version($file_name){ echo $file_name."?".filemtime($_SERVER['DOCUMENT_ROOT'] .$file_name); } 

HTML中

 <script type="text/javascript" src="<?php latest_version('/ao/javascript/almanacka.js'); ?>">< /script> 

怎么运行的:

在HTML中,写入文件filepath和名称,但是仅在函数中。 PHP获取文件的文件时间并返回文件filepath+name+"?"+time最新更改的filepath+name+"?"+time

一个简单的方法。 编辑htaccess

 RewriteEngine On RewriteBase / RewriteCond %{REQUEST_URI} \.(jpe?g|bmp|png|gif|css|js|mp3|ogg)$ [NC] RewriteCond %{QUERY_STRING} !^(.+?&v33|)v=33[^&]*(?:&(.*)|)$ [NC] RewriteRule ^ %{REQUEST_URI}?v=33 [R=301,L] 

一种解决方法是在获取资源时将带有时间戳的查询string追加到URL中。 这利用了这样一个事实,即浏览器不会caching从其中带有查询string的URL获取的资源。

你可能不希望浏览器根本不caching这些资源; 它更可能是您希望他们caching,但您希望浏览器获取该文件的新版本时提供。

最常见的解决scheme似乎是在文件名中embedded时间戳或修订版本号。 这是一个更多的工作,因为你的代码需要修改以请求正确的文件,但这意味着,例如, snazzy_javascript_file.js (即snazzy_javascript_file_7.js )的版本7被caching在浏览器上,直到您发布版本8,然后您的代码将更改为获取snazzy_javascript_file_8.js

最简单的解决scheme 不要让浏览器caching。 附加当前时间(以毫秒为单位)作为查询。

(你还在testing阶段,所以你可以做一个合理的事情来优化性能,但是YMMV在这里)

通过fileV1.js file.js?V=1fileV1.js是,您不需要在服务器上存储多个JavaScript文件版本。

我用file.js?V=1看到的麻烦是,在使用新版本的库工具时,可能会在另一个JavaScript文件中存在依赖代码。

为了向后兼容,我认为使用jQuery.1.3.js来处理新页面,并让现有页面使用jQuery.1.1.js ,直到您准备好升级较旧的页面(如果有必要)为止。

使用版本GETvariables来防止浏览器caching。

?v=AUTO_INCREMENT_VERSION附加到url的末尾可防止浏览器caching – 避免使用任何和所有caching的脚本。

在ASP.NET Core中通过标记助手caching破坏会为你处理,并允许你的浏览器保存caching的脚本/ css,直到文件改变。 只需将标签助手asp-append-version =“true”添加到您的脚本(js)或链接(css)标签:

 <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true"/> 

Dave Paquette在这里有一个很好的例子和caching清除的解释(页面底部) Cache Busting

我们一直在为用户创build一个SaaS,并为他们提供一个脚本来附加到他们的网站页面,而且不可能在脚本上附加一个版本,因为用户会将脚本附加到他们的网站上以实现function,我不能强制他们每次更新脚本时更改版本

所以,我们find了一种在用户每次调用原始脚本时加载新版脚本的方法

脚本链接提供给用户

 <script src="https://thesaasdomain.com/somejsfile.js" data-ut="user_token"></script> 

脚本文件

 if($('script[src^="https://thesaasdomain.com/somejsfile.js?"]').length !== 0) { init(); } else { loadScript("https://thesaasdomain.com/somejsfile.js?" + guid()); } var loadscript = function(scriptURL) { var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.type = 'text/javascript'; script.src = scriptURL; head.appendChild(script); } var guid = function() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } var init = function() { // our main code } 

说明:

用户已经附加在他们的网站提供给他们的脚本,我们检查附加的脚本存在或不使用jQueryselect器的唯一标记,如果没有,然后加载它与新的标记(或版本)

这是两次调用相同的脚本,这可能是一个性能问题,但它确实解决了强制脚本无法从caching中加载的问题,而无需将版本放在实际的脚本链接中给予用户或客户端

免责声明:如果你的情况下性能是一个大问题,不要使用。