我注意到一些浏览器(特别是Firefox和Opera)非常热衷于使用.css和.js文件的缓存副本,甚至在浏览器会话之间。当您更新其中一个文件时,这会导致一个问题,但用户的浏览器会继续使用缓存的副本。

当文件发生更改时,强迫用户浏览器重新加载文件的最优雅的方法是什么?

理想情况下,该解决方案不会强制浏览器在每次访问页面时重新加载文件。


我发现John Millikin和da5id的建议很有用。这有一个专门的术语:自动版本控制。

我在下面发布了一个新的答案,这是我最初的解决方案和约翰的建议的结合。

SCdF建议的另一个想法是将伪查询字符串附加到文件中。(一些自动使用时间戳作为伪查询字符串的Python代码是由pi..提交的)

然而,关于浏览器是否缓存带有查询字符串的文件还存在一些讨论。(请记住,我们希望浏览器缓存该文件并在以后的访问中使用它。我们只希望它在文件更改时再次获取该文件。)


当前回答

谷歌的mod_pagespeed插件将为你自动版本控制。它真的很光滑。

它解析HTML在它的方式从web服务器(与PHP, Ruby on Rails, Python,静态HTML -任何)和重写链接到CSS, JavaScript,图像文件,使他们包括一个id代码。它在修改后的url上提供文件,并对它们进行非常长的缓存控制。当文件更改时,它会自动更改url,因此浏览器必须重新获取它们。它基本上可以正常工作,无需对代码进行任何更改。它甚至还会缩小你的代码。

其他回答

如果你添加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>

我听说这叫做“自动版本控制”。最常见的方法是在URL中包含静态文件的修改时间,并使用重写处理程序或URL配置将其剥离:

参见:

Django中的自动资产版本控制 自动版本你的CSS和JavaScript文件

对于Java Servlet环境,可以查看Jawr库。功能页面解释了它是如何处理缓存的:

Jawr will try its best to force your clients to cache the resources. If a browser asks if a file changed, a 304 (not modified) header is sent back with no content. On the other hand, with Jawr you will be 100% sure that new versions of your bundles are downloaded by all clients. Every URL to your resources will include an automatically generated, content-based prefix that changes automatically whenever a resource is updated. Once you deploy a new version, the URL to the bundle will change as well so it will be impossible that a client uses an older, cached version.

该库还可以简化JavaScript和CSS,但如果不需要,可以将其关闭。

对于在开发和测试时遇到此问题的开发人员:

简单地删除缓存。

“保持缓存与文件一致”..太麻烦了。

一般来说,我不介意加载更多的文件——甚至在大多数项目中加载没有改变的文件——实际上是无关紧要的。在开发应用程序时,我们主要从磁盘加载,在localhost:port上加载,因此网络流量的增加不是一个棘手的问题。

大多数小项目只是玩玩而已——它们从来没有真正投入生产。所以对他们来说,你不需要更多的东西……

因此,如果你使用Chrome DevTools,你可以遵循如下图所示的禁用缓存方法:

如果你有Firefox缓存问题:

只在开发过程中这样做。你还需要一种机制来强制重新加载用于生产,因为如果你频繁地更新你的应用程序,你的用户将使用旧的缓存失效的模块,而你没有提供一个专门的缓存同步机制,就像上面的答案中描述的那样。

是的,这个信息已经在以前的答案中,但我仍然需要做谷歌搜索才能找到它。

我建议执行以下流程:

无论何时部署你的CSS和JavaScript文件。类似于:screen.1233.css(如果您使用版本控制系统,该数字可以是您的SVN版本) 缩小它们以优化加载时间