我注意到一些浏览器(特别是Firefox和Opera)非常热衷于使用.css和.js文件的缓存副本,甚至在浏览器会话之间。当您更新其中一个文件时,这会导致一个问题,但用户的浏览器会继续使用缓存的副本。
当文件发生更改时,强迫用户浏览器重新加载文件的最优雅的方法是什么?
理想情况下,该解决方案不会强制浏览器在每次访问页面时重新加载文件。
我发现John Millikin和da5id的建议很有用。这有一个专门的术语:自动版本控制。
我在下面发布了一个新的答案,这是我最初的解决方案和约翰的建议的结合。
SCdF建议的另一个想法是将伪查询字符串附加到文件中。(一些自动使用时间戳作为伪查询字符串的Python代码是由pi..提交的)
然而,关于浏览器是否缓存带有查询字符串的文件还存在一些讨论。(请记住,我们希望浏览器缓存该文件并在以后的访问中使用它。我们只希望它在文件更改时再次获取该文件。)
这是一个纯JavaScript解决方案
(function(){
// Match this timestamp with the release of your code
var lastVersioning = Date.UTC(2014, 11, 20, 2, 15, 10);
var lastCacheDateTime = localStorage.getItem('lastCacheDatetime');
if(lastCacheDateTime){
if(lastVersioning > lastCacheDateTime){
var reload = true;
}
}
localStorage.setItem('lastCacheDatetime', Date.now());
if(reload){
location.reload(true);
}
})();
上面将查找用户最后一次访问您的站点的时间。如果最后一次访问是在发布新代码之前,它使用location.reload(true)强制从服务器刷新页面。
我通常把这作为<head>中的第一个脚本,因此它在任何其他内容加载之前进行评估。如果需要重新加载,用户很难注意到。
我使用本地存储来存储浏览器上最后一次访问的时间戳,但是如果您希望支持旧版本的IE,您可以添加cookie。
仅在纯JavaScript的本地开发中禁用script.js的缓存。
它会注入一个随机的script.js?Wizardry =1231234并阻塞常规script.js:
<script type="text/javascript">
if(document.location.href.indexOf('localhost') !== -1) {
const scr = document.createElement('script');
document.setAttribute('type', 'text/javascript');
document.setAttribute('src', 'scripts.js' + '?wizardry=' + Math.random());
document.head.appendChild(scr);
document.write('<script type="application/x-suppress">'); // prevent next script(from other SO answer)
}
</script>
<script type="text/javascript" src="scripts.js">
对现有答案的小改进……
使用随机数或会话id将导致它在每个请求时重新加载。理想情况下,我们可能只需要在任何JavaScript或CSS文件中完成一些代码更改时才需要更改。
当使用一个公共JSP文件作为许多其他JSP和JavaScript文件的模板时,请在一个公共JSP文件中添加以下内容
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var = "version" scope = "application" value = "1.0.0" />
现在在JavaScript文件包含的所有位置使用上述变量,如下所示。
<script src='<spring:url value="/js/myChangedFile.js?version=${version}"/>'></script>
优点:
这种方法将帮助您仅在一个位置更改版本号。
维护一个适当的版本号(通常是构建/发布号)将帮助您检查/验证您的代码更改是否被正确部署(从浏览器的开发人员控制台)。
另一个有用的建议:
如果使用Chrome浏览器,可以在打开“开发工具”时禁用缓存。
在Chrome浏览器中,点击F12→F1,滚动到设置→首选项→网络→*禁用缓存(当DevTools打开时)
我们有一个解决方案,有一些不同的实现方式。我们使用上面的解决方案。
datatables?v=1
我们可以处理文件的版本。这意味着每次我们改变文件时,它的版本也会改变。但这不是一个合适的方式。
另一种方法使用GUID。它也不合适,因为每次它都从浏览器缓存中获取文件而不使用。
datatables?v=Guid.NewGuid()
最后一种最好的方法是:
当文件发生更改时,也要更改版本。检查以下代码:
<script src="~/scripts/main.js?v=@File.GetLastWriteTime(Server.MapPath("/scripts/main.js")).ToString("yyyyMMddHHmmss")"></script>
通过这种方式,当您更改文件时,LastWriteTime也会更改,因此文件的版本将会更改,并且在下次打开浏览器时,它会检测到一个新文件并获取它。