强制浏览器清除缓存

有没有一种方法可以让我把一些代码放在我的页面上,这样当有人访问一个网站时,它就会清空浏览器缓存,这样他们就可以查看更改了?

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

746759 次浏览

查看cache - control到期 META标签。

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

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

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

如果这是关于.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.

你可以检查这个链接,看看它是如何工作的。

您是想清除缓存,还是只是确保当前(已更改的?)页面没有缓存?

如果是后者,那就应该如此简单

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

在这里是在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

除了设置Cache-control: no-cache,如果你想每次刷新本地副本,你还应该将Expires头设置为-1(某些版本的IE似乎需要这样做)。

看到HTTP缓存-检查服务器,总是发送If-Modified-Since

不确定这是否真的对你有帮助,但这就是缓存在任何浏览器上的工作方式。当浏览器请求一个文件时,它应该总是向服务器发送请求,除非存在“脱机”模式。服务器将读取一些参数,如日期修改或标记。

服务器将为NOT MODIFIED返回一个304错误响应,浏览器将不得不使用它的缓存。如果标签在服务器端没有验证,或者修改的日期低于当前修改的日期,服务器应该返回带有新的修改日期或标签或两者的新内容。

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

这是应该做的。在url中使用随机参数或版本号更像一个黑客。

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/ < / p >

看了之后,我看到还有一个过期日期。如果你有问题,可能是因为你设置了过期日期。换句话说,当浏览器缓存你的文件时,因为它有一个有效期,所以它不应该在这个日期之前再次请求它。换句话说,它永远不会向服务器请求文件,也永远不会收到一个未修改的304。它将简单地使用缓存,直到达到过期日期或缓存被清除为止。

所以这是我的猜测,你有某种有效期,你应该使用最后修改标签或它们的混合,并确保没有过期日期。

如果人们倾向于频繁地刷新文件,而文件不会经常更改,那么设置一个大的过期日期可能是明智的。

我的2分钱!

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

/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" />

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

更新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年,我发布了一篇关于处理问题中描述的问题的新方法的更新。又过了4年,现在看来它已经被弃用了。感谢cgaldiolo在评论中指出这一点

目前,截至2016年7月,HTML标准,第7.9节,脱机Web应用程序包含一个弃用警告:

此功能正在从Web平台上移除。 (这是一个漫长的过程,需要很多年。)使用任何 此时非常不鼓励使用离线Web应用程序特性。

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

Deprecated
该特性已从Web标准中移除。 虽然一些浏览器可能仍然支持它,但它仍在开发过程中 被删除。不要在旧的或新的项目中使用它。页面或Web应用程序

.

.

.

另见Bug 1204581 -如果启用service worker获取拦截,为AppCache添加弃用通知

我有一个案例,我将在线拍摄客户端的照片,如果照片被更改,就需要更新div。浏览器仍然显示着旧照片。因此,我使用了调用随机GET变量的方法,该变量每次都是唯一的。这就是它,如果它能帮助到任何人的话

<img src="/photos/userid_73.jpg?random=<?php echo rand() ?>" ...
< p >编辑 正如其他人指出的那样,下面是更有效的解决方案,因为它只会在图像被更改时重新加载图像,通过文件大小标识此更改:

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

我实现了这个简单的解决方案(还没有在生产环境中):

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的版本值是否低于当前版本,并执行a

location.reload(true);

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

(显然,您可以使用cookie或其他持久客户端存储而不是localStorage)

我选择这个解决方案是因为它很简单,因为只维护一个“version .txt”文件就会强制重载整个站点。

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

我是一个小新手,我很感激你的专业检查&回顾以确保我的方法是一个好的方法。

希望能有所帮助。

我也遇到过类似的问题,我是这样解决的:

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

    <html manifest="cache.manifest">
    
  2. In <head> section included script updating the cache:

    <script type="text/javascript" src="update_cache.js"></script>
    
  3. In <body> section I've inserted onload function:

    <body onload="checkForUpdate()">
    
  4. In cache.manifest I've put all files I want to cache. It is important now that it works in my case (Apache) just by updating each time the "version" comment. It is also an option to name files with "?ver=001" or something at the end of name but it's not needed. Changing just # version 1.01 triggers cache update event.

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

    包含1是很重要的。2。和3。在index.html中指向只有。否则

    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();
    }
    

Now you just change files and in manifest you have to update version comment. Now visiting index.html page will update the cache.

The parts of solution aren't mine but I've found them through internet and put together so that it works.

很多答案都忽略了一点——大多数开发人员都很清楚关闭缓存是低效的。然而,在许多常见的情况下,效率并不重要,默认缓存行为被严重破坏。

这些包括嵌套的、迭代的脚本测试(大的一个!)和坏的第三方软件变通方法。这里给出的解决方案都不足以解决这种常见场景。大多数web浏览器都有过于激进的缓存,并且没有提供合理的方法来避免这些问题。

有一个小技巧可以使用。诀窍是在脚本标记中向文件名附加一个参数/字符串,并在文件更改时更改它。

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

浏览器将整个字符串解释为文件路径,即使“?”后面的是参数。所以现在发生的事情是,下次当你更新你的文件时,只要改变你网站上的脚本标签中的数字(示例<script src="myfile.js?version=1.0.1"></script>),每个用户的浏览器都会看到文件已经改变,并抓取一个新的副本。

更新URL为以下工作为我:

/custom.js?id=1

通过在?id=之后添加一个唯一的数字,并在有新的变化时将其递增,用户不必按CTRL + F5来刷新缓存。或者,你可以在?id=之后附加当前时间或Epoch的哈希或字符串版本

类似?id=1520606295

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

到目前为止,我发现如果你改变服务器上文件的日期和时间,特定的资源可以单独重新加载。“清除缓存”并不像想象的那么简单。我意识到,“触摸”缓存的服务器文件实际上会改变缓存在服务器上的源文件的日期和时间(在Edge、Chrome和Firefox上测试),大多数浏览器会自动下载你服务器上的最新副本(代码、图形和任何多媒体)。我建议你在程序运行之前复制服务器上最新的脚本和"触摸事物"解决方案,这样它就会将所有问题文件的日期更改为最新的日期和时间,然后它会下载一个新的副本到你的浏览器:

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

然后……剩下的程序…

我花了一些时间来解决这个问题(因为许多浏览器对不同的命令有不同的行为,但它们都检查文件的时间,并将其与浏览器中下载的副本进行比较,如果日期和时间不同,将进行刷新),如果你不能按照假设的正确方式进行,总有另一种可用的更好的解决方案。祝你露营愉快。顺便说一下,touch();或替代工作在许多编程语言,包括javascript bash sh PHP,你可以包括或在html中调用它们。

对于webpack用户:-

我在webpack配置中添加了chunkash。这解决了每次部署时缓存失效的问题。我们还需要注意index.html/ asset。清单不是缓存在你的CDN或浏览器。在webpack配置中的块名配置将看起来像这样:-

文件名:[chunkhash] - $ {Date.now ()} . js

或者如果你使用contenthash那么

文件名:[contenthash] - $ {Date.now ()} . js

这是我在一个使用PHP的应用程序中使用的简单解决方案。

所有JS和CSS文件都放在一个有版本名的文件夹中。例如:“1.0.01”;

root\1.0.01\JS
root\1.0.01\CSS

在那里创建一个Helper并定义版本号

<?php
function system_version()
{
return '1.0.07';
}

和链接JS和SCC文件如下

<script src="<?= base_url(); ?>/<?= system_version();?>/js/generators.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="<?= base_url(); ?>/<?= system_version(); ?>/css/view-checklist.css" />

每当我对任何JS或CSS文件进行更改时,我都会在Helper中更改System Verson并重命名文件夹并部署它。

我有同样的问题,我所做的就是改变文件名链接到我的index.html文件,然后进入index.html文件,更新他们的名字,不是最好的做法,但如果它工作。浏览器将它们视为新文件,因此它们会被重新下载到用户的设备上。

< p >的例子: 我想更新一个css文件,其命名为styles.css,将其更改为styles.css

进入index。html进行更新,并将其更改为

如果感兴趣的话,我已经找到了我的解决方案,让浏览器在.net MVC (.net fw 4.8)的上下文中刷新.css和.js,并使用捆绑包。 我想让浏览器仅在部署新程序集之后刷新缓存文件

根据撒利亚多尼的回答,我的解决方案如下:

  1. 在web配置应用程序设置中存储你的应用程序基础url (HttpContext在RegisterBundle期间运行时还不可用…),然后通过xml转换使这个参数根据配置(调试,登台,发布…
  2. 在BundleConfig中,RegisterBundles通过反射的方式获取程序集版本,并且…
  3. ...更改样式和脚本的默认标记格式,以便捆绑系统生成附加查询字符串参数的链接和脚本标记。

下面是代码

public static void RegisterBundles(BundleCollection bundles)
{
string baseUrl = system.Configuration.ConfigurationManager.AppSettings["by.app.base.url"].ToString();
       

string assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
   

Styles.DefaultTagFormat = $"<link href='{baseUrl}\{\{0}}?v={assemblyVersion}' rel='stylesheet'/>";
Scripts.DefaultTagFormat = $"<script src='{baseUrl}\{\{0}}?v={assemblyVersion}'></script>";
}

你会得到这样的标签

<script src="https://example.org/myscriptfilepath/script.js?v={myassemblyversion}"></script>

您只需要记住在部署之前构建一个新版本。

再见