强制浏览器清除缓存


283

有什么办法可以在页面上放置一些代码,以便当有人访问站点时,它会清除浏览器缓存,以便他们可以查看更改?

使用的语言:ASP.NET,VB.NET,当然还有HTML,CSS和jQuery。


一个很好的解决方案或“清除缓存”的解决方法可以在这里找到:stackoverflow.com/a/43676353/2008111
caramba

Answers:


349

如果这是关于.css.js变化,一种方法是到“缓存无效”是通过附加像“ _versionNo”为每个版本的文件名。例如:

script_1.0.css // This is the URL for release 1.0
script_1.1.css // This is the URL for release 1.1
script_1.2.css // etc.

或者在文件名之后执行此操作:

script.css?v=1.0 // This is the URL for release 1.0
script.css?v=1.1 // This is the URL for release 1.1
script.css?v=1.2 // etc.

您可以查看此链接以查看其工作方式。


10
这是一个相当不错的解决方案,甚至可以由您的构建系统(应该是)自动进行。例如,Stackoverflow使用此方法。
derobert

7
SO现在正在使用GET参数。
Saeb Amini

60
更好的是保持文件名不变,但将版本号附加为querystring参数,即script.js?v=1.2。(或者,如果您不跟踪版本,只需使用文件上次修改的时间即可,这更容易实现)。不知道那是以前的评论者的意思!
Doin 2014年

5
每个人如何通过版本控制来做到这一点?好像真的很痛苦。
肖恩2014年

1
@Shawn版本控制明智的做法是,您可以<link />动态呈现标签,并将应用程序的版本作为查询字符串参数注入。或者,某些CMS将附加“客户端资源版本”作为CMS范围的附加设置-网站的管理员可以手动增加该版本nr,并且CMS的更新还可以自动更新它。底线:您需要动态呈现文件URL。
Jeroen 2014年

103

查看缓存控件到期的 META标签。

<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
<META HTTP-EQUIV="EXPIRES" CONTENT="Mon, 22 Jul 2002 11:12:01 GMT">

另一种常见的做法是将不断变化的字符串附加到请求文件的末尾。例如:

<script type="text/javascript" src="main.js?v=12392823"></script>


44
对于已经被缓存的情况,这无济于事-由于已缓存服务器,因此不会对其进行查询,因此无法响应无缓存。另外,确实不应该使用该元标记,正如注释所述,它将与Web缓存一起中断。
derobert

1
+1德罗伯特说的话。使用HTTP标头向客户端和Web缓存建议缓存策略总是更好,但是即使这样也不能强制重新加载缓存。

4
+1为您的第二个解决方案。我有一个问题,只有在某些管理员进行更新后才应该第一次清除缓存。这种方法应该可以解决
Jules Colle 2010年

完全禁用缓存通常不是一个好主意。
约旦

73

更新2012

这是一个古老的问题,但是我认为它需要更新的答案,因为现在有一种方法可以更好地控制网站缓存。

在“ 脱机Web应用程序”(实际上是任何HTML5网站)applicationCache.swapCache()中,可以使用它来更新网站的缓存版本,而无需手动重新加载页面。

这是HTML5 Rocks上使用应用程序缓存初学者指南中的代码示例,解释了如何将用户更新到您网站的最新版本:

// Check if a new cache is available on page load.
window.addEventListener('load', function(e) {

  window.applicationCache.addEventListener('updateready', function(e) {
    if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
      // Browser downloaded a new app cache.
      // Swap it in and reload the page to get the new hotness.
      window.applicationCache.swapCache();
      if (confirm('A new version of this site is available. Load it?')) {
        window.location.reload();
      }
    } else {
      // Manifest didn't changed. Nothing new to server.
    }
  }, false);

}, false);

另请参阅在Mozilla开发人员网络上使用应用程序缓存

更新2016

网路上的事物变化很快。这个问题是在2009年提出的,2012年,我发布了有关处理问题中所述问题的新方法的更新。又过了四年,现在看来它已经过时了。感谢cgaldiolo在评论中指出。

当前,从2016年7月开始,HTML标准的第7.9节“脱机Web应用程序”包含弃用警告:

该功能正在从Web平台中删除。(这是一个耗时多年的漫长过程。)强烈建议您此时不使用任何脱机Web应用程序功能。请改用服务人员。

在2012年引用的Mozilla开发人员网络上使用应用程序缓存也是如此:

不推荐使用
此功能已从Web标准中删除。尽管某些浏览器可能仍支持它,但是它正在被删除。不要在新旧项目中使用它。使用它的页面或Web应用程序可能随时中断。

另请参见Bug 1204581-如果启用了Service Worker Fetch拦截,则为AppCache添加弃用通知


1
这是否意味着您需要使用和维护缓存清单文件?
山姆

警告:不建议使用应用程序缓存(AppCache)接口
cgaldiolo16年

59
那么,截至2017年的当前建议是什么?
加勒特

在此主题上看到的主要问题是,查看器使用的设备由于用户设备的内部存储器已满而继续使用缓存的版本时。它似乎卡在页面的缓存版本上,并且不会更新文档上的任何元素。这仅发生在铬中吗?多数民众赞成在唯一的浏览器上体验过。
user2585548

4
2017年:使用服务工作者。
digitai

27

并非如此。一种方法是在传递内容时发送适当的标头,以强制浏览器重新加载:

确保未在所有浏览器中缓存网页。

如果"cache header"在SO上进行搜索或类似的搜索,您将找到ASP.NET特定的示例。

如果您无法在服务器端控制标头,另一种不太干净但有时仅是唯一的方法是在被调用的资源中添加随机GET参数:

myimage.gif?random=1923849839

2
正确地对文件进行版本控制确实更好。这是相当大的带宽浪费,而且可能更重要的是,这会使您的网站速度大大降低。
derobert

8
那真的取决于情况,不是吗?如果您正在编写CMS,并且需要确保所有更改的资源都已正确更新,则有时无法解决这两个选项之一。
佩卡

这样的解决方案应该投反对票。保持互联网的二氧化碳排放量尽可能低是我们的责任。
时间

14

对于静态资源,正确的缓存将是使用带有每个部署或文件版本的值的查询参数。这将在每次部署后清除缓存。

/Content/css/Site.css?version={FileVersionNumber}

这是ASP.NET MVC示例。

<link href="@Url.Content("~/Content/Css/Reset.css")?version=@this.GetType().Assembly.GetName().Version" rel="stylesheet" type="text/css" />

不要忘记更新程序集版本。


感谢您提供此答案,但是当我们在BundleTable中添加资源时该怎么做?
toregua

就我而言,这将返回“ 0.0.0.0”作为版本。要获取MVC应用的dll版本,请改用此版本:?version=@ViewContext.Controller.GetType().Assembly.GetName().Version
CGodo 2013年

1
我发现这阻止了Firefox和Chrome完全缓存内容。
2014年

10

我有类似的问题,这就是我解决的方法:

  1. index.html文件中,我添加了清单:

    <html manifest="cache.manifest">
  2. <head>包含脚本的部分中,更新缓存:

    <script type="text/javascript" src="update_cache.js"></script>
  3. 在本<body>节中,我插入了onload函数:

    <body onload="checkForUpdate()">
  4. cache.manifest我已放入所有要缓存的文件中。现在重要的是,对于我的情况(Apache),仅在每次更新“版本”注释时才起作用。也可以使用“?ver = 001”或名称末尾的名称来命名文件,但这不是必需的。更改只是# version 1.01触发缓存更新事件。

    CACHE MANIFEST
    # version 1.01
    style.css
    imgs/logo.png
    #all other files

    在index.html中包含1.,2和3.点很重要。除此以外

    GET http://foo.bar/resource.ext net::ERR_FAILED

    之所以会发生,是因为每个“子”文件都试图在页面已被缓存时缓存该页面。

  5. update_cache.js文件中,我输入了以下代码:

    function checkForUpdate()
    {
        if (window.applicationCache != undefined && window.applicationCache != null)
        {
            window.applicationCache.addEventListener('updateready', updateApplication);
        }
    }
    function updateApplication(event)
    {
        if (window.applicationCache.status != 4) return;
        window.applicationCache.removeEventListener('updateready', updateApplication);
        window.applicationCache.swapCache();
        window.location.reload();
    }

现在,您只需更改文件,然后在清单中就必须更新版本注释。现在访问index.html页面将更新缓存。

解决方案的部分不是我的,但我已经通过互联网找到了它们,并将它们放在一起以使其起作用。


我能知道写在哪里CACHE.MANIFEST。
Shweta Gulati

1
Shweta Gulati清单文件应与“索引”文件位于同一文件夹中。什么时候它不起作用?
Wojtek Mazurek

1
@ShwetaGulati是的,缓存无法检测html文件中的更改-这就是为什么您必须更新清单文件中的版本号的原因,因为它是正在检查更改的版本号。真的很难为您提供帮助,因为我不知道细节。请告诉我,是否已将所有需要缓存的文件放在清单中?路径应相对于清单文件。您可以给我您的网站地址,然后我可以告诉您问题是怎么回事:)
Wojtek Mazurek'Oct9'16

1
@ShwetaGulati这是因为浏览器会自动缓存一些文件,以使页面加载速度更快。这是默认行为,仅取决于浏览器,因此您无法以任何方式进行设置。尤其是js文件属于浏览器范围,因为它们通常在网站上的所有页面上使用,因此缓存它们是明智的。除了在清单文件中写入所有文件名之外,没有其他方法可以缓存所有文件。如果您发现任何问题,请告诉我,因为我也需要它:)
Wojtek Mazurek

1
文件的绝对路径无关紧要。地址的相对路径很重要,因为浏览器发送了文件请求。F.ex:我有一个example.com域,它位于serwer names.com上。我在上面的空间是example.names.com。因此,我将example.com域加入到服务器空间example.names.com中作为重定向。为此,我需要将文件夹设置为此重定向的目标。因此,如果要在example.names.com上创建多个站点,请创建文件夹“ name1”,并将其设置为重定向并将其所有文件放入其中。从这里开始计算路径。如果清单文件中有name1 \ scripts \ test.js,则编写scripts \ test.js。
Wojtek Mazurek

7

我有一种情况,我会在网上为客户拍照,如果更改了照片,则需要更新div。浏览器仍在显示旧照片。因此,我使用了调用随机GET变量的技巧,该变量每次都是唯一的。这是否可以帮助任何人

<img src="/photos/userid_73.jpg?random=<?php echo rand() ?>" ...

编辑正如其他人所指出的那样,以下是更有效的解决方案,因为它仅在更改图像时才重新加载图像,并通过文件大小识别此更改:

<img src="/photos/userid_73.jpg?modified=<? filemtime("/photos/userid_73.jpg")?>"

29
这一点一点都不优雅,它会使站点每次浪费大量时间下载资源时重新加载映像,更好的解决方案是使用filesize而不是随机数,这将使高速缓存仅在文件实际运行时才重新验证变化
Roberto Arosemena 2015年

8
或图像的哈希字节
泰勒Edmiston的

1
这完全取决于用户的要求。对于大量照片,场景将不同于几张照片。检查文件大小将节省带宽,但也会增加额外的处理,从而可能减慢页面加载速度。在我的情况下,图片的更改非常频繁,并且至关重要的业务决策是用户获得最新的图片,这是一个完美的解决方案。
zeeshan 2015年

您甚至可以在配置中将其设为静态值,但这绝不是理想的方法。
Seer 2016年

3
<img src =“ / photos / userid_73.jpg?modified = <?= filemtime(” / photos / userid_73.jpg“)?>”会更加有用!
Fusca Software

4

许多答案都没有抓住重点-大多数开发人员都清楚地知道,关闭缓存效率很低。但是,在许多常见情况下,效率不重要并且严重破坏了默认缓存行为。

这些措施包括嵌套的迭代脚本测试(大!)和损坏的第三方软件变通办法。此处给出的解决方案均不足以解决此类常见情况。大多数Web浏览器的缓存都过于激进,无法提供避免这些问题的明智方法。



2

将URL更新为以下内容对我有用:

/custom.js?id=1

通过在其后添加一个唯一编号?id=并对其进行递增以进行新更改,用户不必按CTRL + F5刷新缓存。或者,您可以在当前时间后添加哈希或字符串版本,或者在?id=

就像是 ?id=1520606295


1

是有关在ASP.NET中设置缓存的MDSN页面。

Response.Cache.SetExpires(DateTime.Now.AddSeconds(60))
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(False)
Response.Cache.VaryByParams("Category") = True

If Response.Cache.VaryByParams("Category") Then
   '...
End If

1

不知道这是否真的对您有帮助,但是这就是缓存在任何浏览器上都应该起作用的方式。当浏览器请求文件时,除非存在“脱机”模式,否则它应始终向服务器发送请求。服务器将读取一些参数,例如修改日期或etags。

服务器将针对“未修改”返回304错误响应,浏览器将不得不使用其缓存。如果etag在服务器端未通过验证,或者修改日期低于当前修改日期,则服务器应返回带有新修改日期或etag或两者兼有的新内容。

如果没有缓存数据发送到浏览器,我猜这种行为是不确定的,浏览器可能会也可能不会缓存不告诉文件如何缓存的文件。如果在响应中设置缓存参数,它将正确缓存文件,然后服务器可以选择返回304错误或新内容。

这是应该做的。在网址中使用随机参数或版本号更像是hack,而不是其他任何东西。

http://www.checkupdown.com/status/E304.html http://en.wikipedia.org/wiki/HTTP_ETag http://www.xpertdeveloper.com/2011/03/last-modified-header-vs- expire-header-vs-etag /

阅读后,我看到还有一个过期日期。如果有问题,则可能是您设置了到期日期。换句话说,当浏览器缓存文件时,由于它具有到期日期,因此不必在该日期之前再次请求它。换句话说,它将永远不会向服务器请求文件,也永远不会收到未修改的304。它将仅使用缓存,直到达到到期日期或清除缓存为止。

所以这就是我的猜测,您有某种到期日期,应该使用上次修改的etags或所有这些的混合使用,并确保没有到期日期。

如果人们倾向于刷新很多并且文件没有做太多更改,那么设置一个较大的到期日期可能是明智的。

我的2美分!


1

我实现了适用于我的简单解决方案(尚未在生产环境中使用):

function verificarNovaVersio() {
    var sVersio = localStorage['gcf_versio'+ location.pathname] || 'v00.0.0000';
    $.ajax({
        url: "./versio.txt"
        , dataType: 'text'
        , cache: false
        , contentType: false
        , processData: false
        , type: 'post'
     }).done(function(sVersioFitxer) {
        console.log('Versió App: '+ sVersioFitxer +', Versió Caché: '+ sVersio);
        if (sVersio < (sVersioFitxer || 'v00.0.0000')) {
            localStorage['gcf_versio'+ location.pathname] = sVersioFitxer;
            location.reload(true);
        }
    });
}

我在html所在的位置有一个小文件:

“ versio.txt”:

v00.5.0014

我的所有页面都调用了此函数,因此在加载时会检查localStorage的版本值是否低于当前版本,并执行

location.reload(true);

...强制从服务器而不是从缓存重新加载。

(显然,可以使用cookie或其他持久客户端存储来代替localStorage)

我之所以选择此解决方案是因为其简单性,因为仅维护单个文件“ versio.txt”将强制重新加载整个网站。

queryString方法难以实现,而且也会被缓存(如果从v1.1更改为以前的版本,则会从缓存中加载,这意味着不会刷新缓存,将所有以前的版本保留在缓存中)。

我是个新手,因此希望您能通过专业的检查和审查,以确保我的方法是一种很好的方法。

希望能帮助到你。



0

可以使用一个技巧,该技巧是在脚本标记中的文件名后面附加一个参数/字符串,并在文件更改时对其进行更改。

<script src="myfile.js?version=1.0.0"></script>

浏览器将整个字符串解释为文件路径,即使“?”之后是什么。是参数。因此,现在发生的麻烦是,下次更新文件时,只需更改网站上脚本标签中的数字(示例<script src="myfile.js?version=1.0.1"></script>),每个用户浏览器都将看到文​​件已更改并获取新副本。


0

强制浏览器清除缓存或重新加载正确的数据?我已经尝试了stackoverflow中描述的大多数解决方案,并且做了一些工作,但是过了一会儿,它最终还是缓存并显示了先前加载的脚本或文件。还有另一种方法可以清除缓存(css,js等)并在所有浏览器上正常工作吗?

到目前为止,我发现如果您更改服务器上文件的日期和时间,则可以分别重新加载特定的资源。“清除缓存”并不是那么容易。我没有清除浏览器上的缓存,而是意识到“触摸”缓存的服务器文件实际上会更改缓存在服务器上的源文件的日期和时间(在Edge,Chrome和Firefox上测试),并且大多数浏览器会自动下载最多服务器上内容的最新副本(代码,图形以及任何多媒体)。我建议您只复制服务器上最新的脚本,然后在程序运行之前“执行触摸操作”解决方案,这样它将把所有问题文件的日期更改为最新的日期和时间,然后下载新的副本。到您的浏览器:

<?php
   touch('/www/sample/file1.css');
   touch('/www/sample/file2.js');
?>

然后...程序的其余部分...

我花了一些时间解决此问题(因为许多浏览器对不同命令的操作不同,但是它们都检查文件的时间并与浏览器中下载的副本进行比较,如果日期和时间不同,则会进行刷新),如果不能以正确的方式前进,总是有另一个可用且更好的解决方案。最好的问候和快乐的露营。顺便说一下touch(); 或替代方法可以在javascript bash sh php等许多编程语言中工作,您可以在html中包含或调用它们。


1
如果修改了文件,则无论如何时间戳都已经更改,因此再次强制它没有任何好处。
Fusca Software

touch命令根本不会更改文件。它更改了日期和时间的属性,将其转换为较新的版本,使浏览器将其下载为新副本。
Luis H Cabrejo

-1

您要清除缓存,还是只是确保当前(已更改?)页面未缓存?

如果是后者,则应尽可能简单

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

我最近在一个Chrome发布中了解了这种方法,并且只在使用Firefox 3.6的少数实时服务器,本地主机和Windows文件共享上找到了一致的结果。
danjah 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.