我注意到一些浏览器(特别是Firefox和Opera)非常热衷于使用.css和.js文件的缓存副本,甚至在浏览器会话之间。当您更新其中一个文件时,这会导致一个问题,但用户的浏览器会继续使用缓存的副本。
当文件发生更改时,强迫用户浏览器重新加载文件的最优雅的方法是什么?
理想情况下,该解决方案不会强制浏览器在每次访问页面时重新加载文件。
我发现John Millikin和da5id的建议很有用。这有一个专门的术语:自动版本控制。
我在下面发布了一个新的答案,这是我最初的解决方案和约翰的建议的结合。
SCdF建议的另一个想法是将伪查询字符串附加到文件中。(一些自动使用时间戳作为伪查询字符串的Python代码是由pi..提交的)
然而,关于浏览器是否缓存带有查询字符串的文件还存在一些讨论。(请记住,我们希望浏览器缓存该文件并在以后的访问中使用它。我们只希望它在文件更改时再次获取该文件。)
对现有答案的小改进……
使用随机数或会话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打开时)
ASP。NET 4.5及以上版本可以使用脚本捆绑。
The request http://localhost/MvcBM_time/bundles/AllMyScripts?v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81 is for the bundle AllMyScripts and contains a query string pair v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81. The query string v has a value token that is a unique identifier used for caching. As long as the bundle doesn't change, the ASP.NET application will request the AllMyScripts bundle using this token. If any file in the bundle changes, the ASP.NET optimization framework will generate a new token, guaranteeing that browser requests for the bundle will get the latest bundle.
捆绑还有其他好处,包括通过缩小页面来提高首次加载时的性能。
仅在纯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">
如果你添加session-id作为JavaScript/CSS文件的伪参数,你可以强制“会话范围缓存”:
<link rel="stylesheet" src="myStyles.css?ABCDEF12345sessionID" />
<script language="javascript" src="myCode.js?ABCDEF12345sessionID"></script>
如果需要版本级缓存,可以添加一些代码来打印文件日期或类似内容。如果您正在使用Java,您可以使用自定义标记以一种优雅的方式生成链接。
<link rel="stylesheet" src="myStyles.css?20080922_1020" />
<script language="javascript" src="myCode.js?20080922_1120"></script>
对于在开发和测试时遇到此问题的开发人员:
简单地删除缓存。
“保持缓存与文件一致”..太麻烦了。
一般来说,我不介意加载更多的文件——甚至在大多数项目中加载没有改变的文件——实际上是无关紧要的。在开发应用程序时,我们主要从磁盘加载,在localhost:port上加载,因此网络流量的增加不是一个棘手的问题。
大多数小项目只是玩玩而已——它们从来没有真正投入生产。所以对他们来说,你不需要更多的东西……
因此,如果你使用Chrome DevTools,你可以遵循如下图所示的禁用缓存方法:
如果你有Firefox缓存问题:
只在开发过程中这样做。你还需要一种机制来强制重新加载用于生产,因为如果你频繁地更新你的应用程序,你的用户将使用旧的缓存失效的模块,而你没有提供一个专门的缓存同步机制,就像上面的答案中描述的那样。
是的,这个信息已经在以前的答案中,但我仍然需要做谷歌搜索才能找到它。