我如何强制客户端刷新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=1
的fileV1.js
是,您不需要在服务器上存储多个JavaScript文件版本。
我用file.js?V=1
看到的麻烦是,在使用新版本的库工具时,可能会在另一个JavaScript文件中存在依赖代码。
为了向后兼容,我认为使用jQuery.1.3.js
来处理新页面,并让现有页面使用jQuery.1.1.js
,直到您准备好升级较旧的页面(如果有必要)为止。
使用版本GET
variables来防止浏览器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中加载的问题,而无需将版本放在实际的脚本链接中给予用户或客户端
免责声明:如果你的情况下性能是一个大问题,不要使用。