如何将时间戳附加到 <script> 标记 url 中的 javascript 文件以避免缓存
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11467873/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to append timestamp to the javascript file in <script> tag url to avoid caching
提问by Seeker
I want to append a random number or a timestamp at the end of the javascript file source path in so that every time the page reloads it should download a fresh copy.
我想在 javascript 文件源路径的末尾附加一个随机数或时间戳,以便每次重新加载页面时都应该下载一个新副本。
it should be like
它应该像
<script type="text/javascript" src="/js/1.js?v=1234455"/>
How can i generate and append this number? This is a simple HTML page, so cant use any PHP or JSP related code
我如何生成和附加这个数字?这是一个简单的 HTML 页面,因此不能使用任何 PHP 或 JSP 相关代码
回答by TheBlackBenzKid
Method 1
方法一
Lots of extensions can be added this way including Asynchronous inclusion and script deferring. Lots of ad networks and hi traffic sites use this approach.
许多扩展可以通过这种方式添加,包括异步包含和脚本延迟。许多广告网络和高流量网站都使用这种方法。
<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>
Method 2 (AJZane's comment)
方法 2(AJZane 的评论)
Small and robust inclusion. You can see exactly where JavaScript is fired and it is less customisable (to the point) than Method 1.
小而坚固的内含物。您可以准确地看到 JavaScript 被触发的位置,并且与方法 1 相比,它的可定制性(就这一点而言)更少。
<script>document.write("<script type='text/javascript' src='//site.com
/js.js?v=" + Date.now() + "'><\/script>");</script>
回答by epoch
Insert the script dynamically via document.createElement('script')
, then when you set the URL, you can use new Date().getTime()
to append the extra parameter.
通过 动态插入脚本document.createElement('script')
,然后在设置 URL 时,可以使用new Date().getTime()
附加额外参数。
If you are worried about your javascript executing before the script is loaded, you can use the onload
callback of the script element (note that there are a few hoops to jump for IE though)
如果你担心你的 javascript 在脚本加载之前执行,你可以使用onload
script 元素的回调(注意,虽然有一些 IE 跳转)
回答by LWurm
If you choose to use dates or a random numbers to append to your URI, you will provide opportunities for the end user to be served the same cached file andmay potentially expose unintended security risks. An explicit versioning system would not. Here's why:
如果您选择使用日期或随机数附加到您的 URI,您将为最终用户提供获得相同缓存文件的机会,并且可能会暴露意外的安全风险。明确的版本控制系统不会。原因如下:
Why "Random" and Random Numbers are both BAD
为什么“随机”和随机数都不好
For random numbers, you have no guarantee that same random number hasn't been generated and served to that user before. The likelihood of generating the same string is greater with smaller "random" number sets, or poor algorithms that provide the same results more often than others. In general, if you are relying on the JavaScript random method, keep in mind it's pseudo-random, and could have security implications as well if you are trying to rely on uniqueness for say a patch in one of your scripts for XSS vulnerabilities or something similar. We don't want Johnny to get served the old cached and unpatched JS file with an AJAX call to a no-longer trusted 3rd-party script the day Mr. Hacker happened to be visiting.
对于随机数,您无法保证之前没有生成相同的随机数并将其提供给该用户。使用较小的“随机”数字集或比其他算法更频繁地提供相同结果的糟糕算法,生成相同字符串的可能性更大。一般来说,如果您依赖 JavaScript 随机方法,请记住它是伪随机的,并且如果您试图依赖唯一性,例如在您的脚本之一中针对 XSS 漏洞或其他问题的补丁,则可能会产生安全隐患相似的。我们不希望 Johnny 在 Hacker 先生碰巧访问的那一天通过 AJAX 调用获得不再受信任的 3rd 方脚本的旧缓存和未修补的 JS 文件。
Why dates or timestamps are bad too, but not as bad
为什么日期或时间戳也很糟糕,但没有那么糟糕
Regarding Dates as "unique" identifiers, JavaScript would be generating the Date object from the client's end. Depending on the date format, your chances for unintended caching may vary. Date alone (20160101) allows a full day's worth of potential caching issues because a visit in the morning results in foo.js?date=20160101, and so does a visit in the evening. Instead, if you specify down to the second (20160101000000) your odds of an end user calling the same GET parameter go down, but still exist.
将日期视为“唯一”标识符,JavaScript 将从客户端生成日期对象。根据日期格式,意外缓存的机会可能会有所不同。仅日期 (20160101) 就允许一整天的潜在缓存问题,因为早上的访问会导致foo.js?date=20160101,晚上的访问也是如此。相反,如果您指定到第二个 (20160101000000),最终用户调用相同 GET 参数的几率会下降,但仍然存在。
A few rare but possible exceptions:
一些罕见但可能的例外:
Clocks get reset (fall behind) once a year in most time zones
Computers that reset their local time on reboot for one reason or another
Automatic network time syncing causing your clock to adjust backwards a few seconds/minutes whenever your local time is off from the server time
Adjusting time zones settings when traveling (The astronauts on the IIStravel through a zone every few minutes...let's not degrade their browsing experience :P)
The user likes resetting their system clock to mess with you
在大多数时区,时钟每年重置一次(落后)
由于某种原因在重新启动时重置本地时间的计算机
自动网络时间同步使您的时钟向后调整几秒/分钟,只要您的本地时间与服务器时间不同
旅行时调整时区设置(IIS上的宇航员每隔几分钟就会穿过一个区域……我们不要降低他们的浏览体验:P)
用户喜欢重置他们的系统时钟来惹你
Why incremental or unique versioning is good :)
为什么增量或唯一版本控制是好的 :)
For a fontend only solution, my suggestion would be to set an explicit version, which could be simply hard-coded by you or your team members every time you change the file. Manually doing exactly as you had done in your same code of your question would be a good practice.
对于仅限 fontend 的解决方案,我的建议是设置一个显式版本,每次更改文件时,您或您的团队成员都可以简单地对其进行硬编码。完全按照您在问题的相同代码中所做的手动操作将是一个很好的做法。
You or your team should be the only ones editing your JS files, so the key take away isn't that your file needs to be served fresh every time, I just needs to be served fresh when it changes. Browser caching isn't a bad thing in your case, but you do need to tell the end user WHENit should update. Essentially, when your file is updated, you want to ensure the client gets the updated copy. With this, you also have the added bonus of being able to revert to previous versions of your code without worry of client caching issues. The only drawback is you need to use due diligence to make sure you actually update the version number when you update your JS files. Keep in mind just because something isn't automated, doesn't mean it is necessarily bad practice or poor form. Make your solution work for your situation and the resources you have available.
你或你的团队应该是唯一编辑你的 JS 文件的人,所以关键不是你的文件每次都需要更新,我只需要在它改变时更新。浏览器缓存在您的情况下并不是一件坏事,但您确实需要告诉最终用户何时它应该更新。本质上,当您的文件更新时,您希望确保客户端获得更新的副本。有了这个,您还有一个额外的好处,即能够恢复到以前的代码版本,而不必担心客户端缓存问题。唯一的缺点是您需要使用尽职调查来确保您在更新 JS 文件时确实更新了版本号。请记住,仅仅因为某些事情不是自动化的,并不意味着它一定是不好的做法或糟糕的形式。让您的解决方案适合您的情况和您可用的资源。
I suggest using a form like Semantic Versioning'srules to easily identify backwards or breaking compatibility by looking at the file name (assuming nobody in the development process fudged up their version numbering) if possible. Unless you have an odd use case, there is no good reason to force a fresh copy down to the client every time.
如果可能的话,我建议使用像语义版本控制规则这样的形式,通过查看文件名(假设开发过程中没有人捏造他们的版本编号)来轻松识别向后或破坏兼容性。除非您有一个奇怪的用例,否则没有充分的理由每次都将新副本强制下发给客户端。
Automated version incrementing on the client side with Local Storage
使用本地存储在客户端自动增加版本
If what you were after was frontend way to automate the generation of a unique version number for you so you don't have to explicitly set it, then you would have to implement some sort of local storage method to keep track of, and auto increment your file versions. The solution I've shown below would lose the ability for Semantic versioning, and also has the potential to be reset if the user knows how to clear Local Storage. However, considering your options are limited to client-side only solutions, this may be your best bet:
如果您所追求的是为您自动生成唯一版本号的前端方式,因此您不必显式设置它,那么您将必须实现某种本地存储方法来跟踪和自动递增你的文件版本。我在下面展示的解决方案将失去语义版本控制的能力,如果用户知道如何清除本地存储,也有可能被重置。但是,考虑到您的选择仅限于客户端解决方案,这可能是您最好的选择:
<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>
I'm going to mention for completeness, if you are converting from an old system of generating "random" numbered or dated GET variables, to an incrementing versioned system, be sure that you will not step over any potentially randomly generated files names with your new versioning system. If in doubt, add a prefix to your GET variable when changing methods, or simply add a new GET variable all together. Example: "foo.js?version=my_prefix_121216" or "foo.js?version=121216&version_system=incremental"
为了完整起见,我要提一下,如果您要从生成“随机”编号或日期 GET 变量的旧系统转换为递增版本系统,请确保您不会使用您的文件跳过任何可能随机生成的文件名新的版本控制系统。如果有疑问,请在更改方法时为 GET 变量添加前缀,或者简单地一起添加一个新的 GET 变量。示例:“foo.js?version=my_prefix_121216”或“foo.js?version=121216&version_system=incremental”
Automated versioning via AJAX calls and other methods (if backend development is a possiblity)
通过 AJAX 调用和其他方法自动版本控制(如果后端开发是可能的)
Personally, I like to stay away from local storage options. If the option isavailable, it would be the "best" solution. Try to get a backend developer make an endpoint to track JS file versions, you could always use the response to that endpoint determine your version number. If you are already using version control like Git, you could optionally have on of your Dev Ops team bind your versioning to your commit versions for some pretty sweet integration as well.
就个人而言,我喜欢远离本地存储选项。如果该选项是可用的,这将是“最佳”的解决方案。尝试让后端开发人员创建一个端点来跟踪 JS 文件版本,您始终可以使用对该端点的响应来确定您的版本号。如果你已经在使用 Git 等版本控制,你可以选择让你的 Dev Ops 团队将你的版本控制绑定到你的提交版本,以获得一些非常好的集成。
A jQuery solution to a RESTfulGET endpoint might look like:
RESTfulGET 端点的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>");
});
回答by Jitendra Pancholi
If you can't user server side code then you can use getScript method to do the same.
如果你不能使用服务器端代码,那么你可以使用 getScript 方法来做同样的事情。
$(document).ready(function(){
var randomNum = Math.ceil(Math.random() * 999999);
var jsfile = 'scripts/yourfile.js?v=' + randomNum;
$.getScript(jsfile, function(data, textStatus, jqxhr) { });
});
Reference URL: http://api.jquery.com/jQuery.getScript/
参考网址:http: //api.jquery.com/jQuery.getScript/
(Please don't forget to mark as answer.)
(请不要忘记标记为答案。)
回答by Madman
Load scripts manually or with jQuery http://api.jquery.com/jQuery.getScript/. It also provides option to prevent chaching
手动或使用 jQuery http://api.jquery.com/jQuery.getScript/加载脚本。它还提供了防止chaching的选项
回答by Beat Richartz
You can replace the source of the script doing this with pure Javascript
您可以使用纯 Javascript 替换执行此操作的脚本源
// get first script
var script = document.getElementsByTagName('script')[0]
var new = document.createElement("script");
// add the source with a timestamp
new.src = 'yoursource.js?' + new Date.getTime().toString();
new.type = 'text/javascript'
script.parentNode.insertBefore(new,script);
回答by Gregory Bologna
Replace regular expression if not alphanumeric Date.prototype.toISOString()
如果不是字母数字则替换正则表达式 Date.prototype.toISOString()
var today = new Date();
"MyFile_" + today.toISOString().replace(/[^\w]/g, "") + ".pdf"
MyFile_20191021T173426146Z.pdf
MyFile_20191021T173426146Z.pdf
回答by rs1
Old post but here is a one liner:
旧帖子,但这里有一个单行:
<script src="../Scripts/source/yourjsname.js?ver<%=DateTime.Now.Ticks.ToString()%>" type="text/javascript"></script>