我注意到一些浏览器(特别是Firefox和Opera)非常热衷于使用.css和.js文件的缓存副本,甚至在浏览器会话之间。当您更新其中一个文件时,这会导致一个问题,但用户的浏览器会继续使用缓存的副本。
当文件发生更改时,强迫用户浏览器重新加载文件的最优雅的方法是什么?
理想情况下,该解决方案不会强制浏览器在每次访问页面时重新加载文件。
我发现John Millikin和da5id的建议很有用。这有一个专门的术语:自动版本控制。
我在下面发布了一个新的答案,这是我最初的解决方案和约翰的建议的结合。
SCdF建议的另一个想法是将伪查询字符串附加到文件中。(一些自动使用时间戳作为伪查询字符串的Python代码是由pi..提交的)
然而,关于浏览器是否缓存带有查询字符串的文件还存在一些讨论。(请记住,我们希望浏览器缓存该文件并在以后的访问中使用它。我们只希望它在文件更改时再次获取该文件。)
在Laravel (PHP)中,我们可以以以下清晰而优雅的方式(使用文件修改时间戳)做到这一点:
<script src="{{ asset('/js/your.js?v='.filemtime('js/your.js')) }}"></script>
CSS也是如此
<link rel="stylesheet" href="{{asset('css/your.css?v='.filemtime('css/your.css'))}}">
示例HTML输出(filemtime返回时间作为Unix时间戳)
<link rel="stylesheet" href="assets/css/your.css?v=1577772366">
假设你有一个文件可用:
/styles/screen.css
你可以在URI上附加一个包含版本信息的查询参数,例如:
/styles/screen.css?v=1234
或者你可以在前面加上版本信息,例如:
/v/1234/styles/screen.css
恕我直言,第二种方法更适合CSS文件,因为它们可以使用相对url引用图像,这意味着如果你指定一个背景图像,像这样:
body {
background-image: url('images/happy.gif');
}
它的URL实际上是:
/v/1234/styles/images/happy.gif
这意味着如果您更新了使用的版本号,服务器将将其视为新资源,而不是使用缓存的版本。如果您的版本号基于Subversion、CVS等版本,这意味着CSS文件中引用的图像的更改将被注意到。第一种方案并不能保证这一点,即URL images/happy.gif相对于/styles/screen.css?V =1235是/styles/images/happy.gif,它不包含任何版本信息。
I have implemented a caching solution using this technique with Java servlets and simply handle requests to /v/* with a servlet that delegates to the underlying resource (i.e. /styles/screen.css). In development mode I set caching headers that tell the client to always check the freshness of the resource with the server (this typically results in a 304 if you delegate to Tomcat's DefaultServlet and the .css, .js, etc. file hasn't changed) while in deployment mode I set headers that say "cache forever".
对现有答案的小改进……
使用随机数或会话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打开时)