我想在 javascript 文件源路径的末尾附加一个随机数或时间戳,以便每次重新加载页面时都应该下载一个新副本。
它应该像
<script type="text/javascript" src="/js/1.js?v=1234455"/>
我如何生成和附加这个数字?这是一个简单的 HTML 页面,因此不能使用任何 PHP 或 JSP 相关代码
我想在 javascript 文件源路径的末尾附加一个随机数或时间戳,以便每次重新加载页面时都应该下载一个新副本。
它应该像
<script type="text/javascript" src="/js/1.js?v=1234455"/>
我如何生成和附加这个数字?这是一个简单的 HTML 页面,因此不能使用任何 PHP 或 JSP 相关代码
方法一
许多扩展可以通过这种方式添加,包括异步包含和脚本延迟。许多广告网络和高流量网站都使用这种方法。
<script type="text/javascript">
(function(){
var randomh=Math.random();
var e = document.getElementsByTagName("script")[0];
var d = document.createElement("script");
d.src = "//site.com/js.js?x="+randomh+"";
d.type = "text/javascript";
d.async = true;
d.defer = true;
e.parentNode.insertBefore(d,e);
})();
</script>
方法 2(AJZane 的评论)
小而坚固的内含物。您可以准确地看到 JavaScript 被触发的位置,并且与方法 1 相比,它的可定制性(就这一点而言)更少。
<script>document.write("<script type='text/javascript' src='//site.com
/js.js?v=" + Date.now() + "'><\/script>");</script>
如果您选择使用日期或随机数附加到您的 URI,您将为最终用户提供获得相同缓存文件的机会,并且可能会暴露意外的安全风险。明确的版本控制系统不会。原因如下:
为什么“随机”和随机数都不好
对于随机数,您无法保证之前没有生成相同的随机数并将其提供给该用户。使用较小的“随机”数字集,或者比其他算法更频繁地提供相同结果的糟糕算法,生成相同字符串的可能性更大。一般而言,如果您依赖 JavaScript 随机方法,请记住它是伪随机的,并且如果您试图依赖唯一性,例如您的脚本中的一个补丁针对 XSS 漏洞或其他问题,则可能会产生安全隐患相似的。我们不希望 Johnny 在 Hacker 先生碰巧访问的那一天通过 AJAX 调用获得不再受信任的 3rd 方脚本的旧缓存和未修补的 JS 文件。
为什么日期或时间戳也很糟糕,但没有那么糟糕
将日期视为“唯一”标识符,JavaScript 将从客户端生成日期对象。根据日期格式,意外缓存的机会可能会有所不同。仅日期 (20160101) 就允许一整天的潜在缓存问题,因为早上的访问会导致foo.js?date=20160101,晚上的访问也是如此。相反,如果您指定到第二个 (20160101000000),最终用户调用相同 GET 参数的几率会下降,但仍然存在。
一些罕见但可能的例外:
在大多数时区,时钟每年重置一次(落后)
由于某种原因在重新启动时重置本地时间的计算机
自动网络时间同步使您的时钟向后调整几秒/分钟,只要您的本地时间与服务器时间不同
旅行时调整时区设置(IIS上的宇航员每隔几分钟就会穿过一个区域......让我们不要降低他们的浏览体验:P)
用户喜欢重置他们的系统时钟来惹你
为什么增量或唯一版本控制是好的 :)
对于仅限 fontend 的解决方案,我的建议是设置一个显式版本,每次更改文件时,您或您的团队成员都可以简单地对其进行硬编码。完全按照您在问题的相同代码中所做的手动操作将是一个很好的做法。
你或你的团队应该是唯一编辑你的 JS 文件的人,所以关键不是你的文件每次都需要更新,我只需要在它改变时更新。浏览器缓存在您的情况下并不是一件坏事,但您确实需要告诉最终用户何时它应该更新。本质上,当您的文件更新时,您希望确保客户端获得更新的副本。有了这个,您还有一个额外的好处,即能够恢复到以前的代码版本,而不必担心客户端缓存问题。唯一的缺点是您需要尽职调查以确保您在更新 JS 文件时确实更新了版本号。请记住,仅仅因为某些事情不是自动化的,并不意味着它一定是不好的做法或糟糕的形式。使您的解决方案适合您的情况和您可用的资源。
如果可能的话,我建议使用像语义版本控制规则这样的形式,通过查看文件名(假设开发过程中没有人捏造他们的版本编号)来轻松识别向后或破坏兼容性。除非您有一个奇怪的用例,否则没有充分的理由每次都将新副本强制下发给客户端。
使用本地存储在客户端自动增加版本
如果您所追求的是为您自动生成唯一版本号的前端方式,因此您不必显式设置它,那么您将必须实现某种本地存储方法来跟踪和自动递增你的文件版本。我在下面展示的解决方案将失去语义版本控制的能力,如果用户知道如何清除本地存储,也有可能被重置。但是,考虑到您的选择仅限于客户端解决方案,这可能是您最好的选择:
<script type="text/javascript">
(function(){
/**
* Increment and return the local storage version for a given JavaScript file by name
* @param {string} scriptName Name of JavaScript file to be versioned (including .js file extension)
* @return {integer} New incremented version number of file to pass to .js GET parameter
*/
var incrementScriptVer = function(scriptName){
var version = parseInt(localStorage.getItem(scriptName));
// Simple validation that our item is an integer
if(version > 0){
version += 1;
} else {
// Default to 1
version = 1;
}
localStorage.setItem(scriptName, version);
return version;
};
// Set your scripts that you want to be versioned here
var scripts = ['foo.js', 'bar.js', 'baz.js'];
// Loop through each script name and append our new version number
scripts.map(function(script){
var currentScriptVer = incrementScriptVer(script);
document.write("<script language='text/javascript' type='text/javascript' src='http://yoursite.com/path/to/js/" + script + "?version=" + currentScriptVer + " '><\/script>");
});
})();
</script>
为了完整起见,我要提一下,如果您要从生成“随机”编号或日期 GET 变量的旧系统转换为递增版本系统,请确保您不会越过任何可能随机生成的文件名新的版本控制系统。如果有疑问,请在更改方法时为您的 GET 变量添加一个前缀,或者简单地一起添加一个新的 GET 变量。示例:“foo.js?version=my_prefix_121216”或“foo.js?version=121216&version_system=incremental”
通过 AJAX 调用和其他方法自动版本控制(如果后端开发是可能的)
就个人而言,我喜欢远离本地存储选项。如果该选项是可用的,这将是“最佳”的解决方案。尝试让后端开发人员创建一个端点来跟踪 JS 文件版本,您始终可以使用对该端点的响应来确定您的版本号。如果你已经在使用 Git 等版本控制,你可以选择让你的 Dev Ops 团队将你的版本控制绑定到你的提交版本,以获得一些非常好的集成。
RESTful GET 端点的jQuery 解决方案可能如下所示:
var script = "foo.js";
// Pretend this endpoint returns a valid JSON object with something like { "version": "1.12.20" }
$.ajax({
url: "//yoursite.com/path/to/your/file/version/endpoint/" + script
}).done(function(data) {
var currentScriptVer = data.version;
document.write("<script language='text/javascript' type='text/javascript' src='http://yoursite.com/path/to/js/" + script + "?version=" + currentScriptVer + " '><\/script>");
});
通过 动态插入脚本document.createElement('script'),然后在设置 URL 时,可以使用new Date().getTime()附加额外参数。
如果你担心你的 javascript 在脚本加载之前执行,你可以使用onloadscript 元素的回调(注意,虽然有一些 IE 跳转)
如果您不能使用服务器端代码,那么您可以使用 getScript 方法来做同样的事情。
$(document).ready(function(){
var randomNum = Math.ceil(Math.random() * 999999);
var jsfile = 'scripts/yourfile.js?v=' + randomNum;
$.getScript(jsfile, function(data, textStatus, jqxhr) { });
});
参考网址:http : //api.jquery.com/jQuery.getScript/
(请不要忘记标记为答案。)
手动或使用 jQuery http://api.jquery.com/jQuery.getScript/加载脚本。它还提供了防止chaching的选项