清除JavaScript中的缓存


179

如何使用JavaScript清除浏览器缓存?

我们部署了最新的JavaScript代码,但无法获取最新的JavaScript代码。

编者注:该问题在以下地方被半复制,以下第一个问题的答案可能是最好的。这个公认的答案不再是理想的解决方案。

如何强制浏览器重新加载缓存的CSS / JS文件?

如何强制客户端刷新JavaScript文件?

动态重新加载本地Javascript源/ json数据


5
这使我感到困惑:“我们部署了最新的javascript代码,但我们无法获得最新的javascript代码”
instanceof me

14
我想你的意思是,如何强制客户端浏览器使用最新版本的javascript,而不是其缓存的版本-在这种情况下,您需要Greg的回答。如果您想知道如何在自己的浏览器中执行此操作,这是David Johnstone的答案。
Benjol


4
一种常见的方法是?version=xxx通过构建步骤将一个附加到您的JS链接文件。每个新版本都将请求JS文件的新版本。
Juan Mendes 2012年

1
@JuanMendes这并不总是有效。当人们在尝试查看最新的网站图标时遇到问题时,建议执行相同的步骤。只是不能保证能正常工作。
uSeRnAmEhAhAhAhAhA14年

Answers:


202

您可以调用window.location.reload(true)重新加载当前页面。它将忽略所有缓存的项目,并从服务器检索页面,css,图像,JavaScript等的新副本。这不会清除整个缓存,但是会清除您所在页面的缓存。

但是,最好的策略是按照其他答案中所述的方式对路径或文件名进行版本控制。此外,请参阅修订文件名:出于不用?v=n作版本控制方案的原因,请勿使用querystring


6
哇谢谢!这也适用于从cache.manifest文件加载的HTML5应用程序缓存。我有一个未从内存中删除的旧清单,因此缓存了该清单的浏览器不会显示较新的文件。我在javascript控制台中键入了此命令,并且运行良好。谢谢!
JayCrossler 2010年

2
但是通过更改文件名进行修改...难道不是您将所有以前的版本都保留了吗?否则,您会从搜索引擎中获得很多失败的尝试,并且不阅读较旧的版本(或带书签/链接的图像)
Rodolfo 2012年

1
我怎么没想到呢,请坦克
osdamv

1
这与用户单击刷新按钮一样吗?
2014年

2
@Manuel它只会禁止从您调用location.reload(true)的确切URL的缓存中访问页面。它永远不会从缓存中清除原始页面,因为它只是将时间戳添加到新请求上,并且如果此页面异步进行其他调用,这些请求将不会禁用其缓存行为。例如。如果使用reload(true)刷新了一个加载了某些html的页面,并且该页面具有一个脚本,该脚本会再次调用ajax,以使更多html显示在同一页面上,则第二个请求将不会禁用其缓存。
J. Schei

114

您无法使用javascript清除缓存。一种常见的方法是将修订号或上次更新的时间戳附加到文件中,如下所示:

myscript.123.js

要么

myscript.js?updated=1234567890


9
但是请注意,当文件具有查询字符串时,许多代理不会缓存该文件。参见Kevin Hakanson的答案
chiborg 2012年

4
整个HTML都已缓存后,如何清除缓存?即使由于缓存的HTML而添加了版本号,它也不会影响。请帮忙
Nandakumar

如果我无法清除缓存项,那么MDN为什么会我可以?我想念什么?我尝试了MDN所说的但没有运气。
SнаSошƒаӽ16

41

尝试更改JavaScript文件的src吗?由此:

<script language="JavaScript" src="js/myscript.js"></script>

对此:

<script language="JavaScript" src="js/myscript.js?n=1"></script>

此方法应强制您的浏览器加载JS文件的新副本。


n = 1是做什么的?
KyelJdD

除了有所不同,它什么也没做。可能是?12345或?Kyle
Oneezy

因此,文件名也需要更改吗?还是只是需要更改的src路径?
弗雷德A

20

除了每小时或每周缓存以外,您还可以根据文件数据缓存。

示例(在PHP中):

<script src="js/my_script.js?v=<?=md5_file('js/my_script.js')?>"></script>

甚至使用文件修改时间:

<script src="js/my_script.js?v=<?=filemtime('js/my_script.js')?>"></script>

3
我可以验证我是否正确理解吗?:使用选项1,当文件更改时,md5校验和哈希值更改,然后更改了url。浏览器将看到一个新的URL,并开始重新加载文件。服务器将忽略附加到URL的获取数据。如果真是这样,那该死的很漂亮。
Colin Brogan

1
另外,对整个文件处理器进行MD5处理是否繁琐?我正在考虑对css和js文件进行此操作,但是由于这个原因,我不希望看到服务器速度受到影响。
柯林·布罗根

2
使用校验和是一个好主意,但应该正确进行。计算每个文件的每个请求将显着影响您的性能。Querystring也不适合缓存,请参阅其他答案。正确的用法是在文件名后附加校验和(部分?)或版本号,并改用这个新名称(您可以使用构建脚本在部署时自动执行此操作)。请参阅 gruntrevusemin
Frizi 2013年

10

您也可以像这样在PHP中强制每小时重新加载代码:

<?php
echo '<script language="JavaScript" src="js/myscript.js?token='.date('YmdH').'">';
?>

要么

<script type="text/javascript" src="js/myscript.js?v=<?php echo date('YmdHis'); ?>"></script>

1
嗨,“ v”和“令牌”是什么意思?
GMsoF

4
@GMsoF只是一个附加的get参数,用于(在这种情况下)告诉浏览器它是一个“不同”的文件。这样浏览器将丢弃缓存的版本并加载该版本。这通常与文件的“最后修改日期”一起使用。我希望这是有道理的;-)
Jelmer,2014年

6

将其放在模板的末尾:

var scripts =  document.getElementsByTagName('script');
var torefreshs = ['myscript.js', 'myscript2.js'] ; // list of js to be refresh
var key = 1; // change this key every time you want force a refresh
for(var i=0;i<scripts.length;i++){ 
   for(var j=0;j<torefreshs;j++){ 
      if(scripts[i].src && (scripts[i].src.indexOf(torefreshs[j]) > -1)){
        new_src = scripts[i].src.replace(torefreshs[j],torefreshs[j] + 'k=' + key );
        scripts[i].src = new_src; // change src in order to refresh js
      } 
   }
}

1
请提供有关您的解决方案的一些说明
Gabriel Espinoza,

@GabrielEspinoza他使用javascript重新加载了文件,从而使缓存得以更新。
Neo Morina

6

尝试使用这个

 <script language="JavaScript" src="js/myscript.js"></script>

对此:

 <script language="JavaScript" src="js/myscript.js?n=1"></script>

5

这是我最新项目使用的片段。

从控制器:

if ( IS_DEV ) {
    $this->view->cacheBust = microtime(true);
} else {
    $this->view->cacheBust = file_exists($versionFile) 
        // The version file exists, encode it
        ? urlencode( file_get_contents($versionFile) )
        // Use today's year and week number to still have caching and busting 
        : date("YW");
}

从视图:

<script type="text/javascript" src="/javascript/somefile.js?v=<?= $this->cacheBust; ?>"></script>
<link rel="stylesheet" type="text/css" href="/css/layout.css?v=<?= $this->cacheBust; ?>">

我们的发布过程会生成一个文件,其中包含当前版本的修订号。通过对文件进行URL编码并将其用作缓存无效化程序,可以实现此目的。作为故障转移,如果该文件不存在,则使用年和周号,以便仍然可以使用缓存,并且至少每周刷新一次。

另外,这在开发环境中为每个页面加载提供了缓存清除功能,因此开发人员不必担心清除任何资源(javascript,css,ajax调用等)的缓存。


5

或者您可以只使用file_get_contets通过服务器读取js文件,然后将js内容放入回显头中


4

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

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

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

我花了一些时间解决此问题(许多浏览器对不同的命令采取不同的操作,但是它们都检查文件的时间并与浏览器中下载的副本进行比较,如果日期和时间不同,则会进行刷新),如果不能以正确的方式前进,总是有另一个可用且更好的解决方案。最好的问候和快乐的露营。


1
我喜欢这种方法,但是也许我在错误的地方实现了这种方法?有人知道在WordPress设置中将其添加到何处吗?我将其添加到functions.php文件中,该文件具有指向JavaScript和CSS文件的直接链接,但是我仍然必须进行重新加载以使更改被注意到。
flipflopmedia

1
您需要做的是在主html wordpress目录中,编辑index.php以调用或执行Touch()命令,以刷新和下载您需要的文件。我遇到了小图片和js文件卡在缓存中的问题。我尝试了描述的大多数方法从内存中释放,但是最好的方法是加载最新的正确方法。您可以通过仅执行“ Touch Thing”来完成操作,因为它不会修改文件上的任何内容,只会更新当前时间和日期,从而使您的浏览器傻瓜认为文件的另一个版本和已解决的问题。适用于大多数浏览器
Luis H Cabrejo

3

我对yboussard建议的代码有些麻烦。内部j循环无效。这是我成功使用的修改后的代码。

function reloadScripts(toRefreshList/* list of js to be refresh */, key /* change this key every time you want force a refresh */) {
    var scripts = document.getElementsByTagName('script');
    for(var i = 0; i < scripts.length; i++) {
        var aScript = scripts[i];
        for(var j = 0; j < toRefreshList.length; j++) {
            var toRefresh = toRefreshList[j];
            if(aScript.src && (aScript.src.indexOf(toRefresh) > -1)) {
                new_src = aScript.src.replace(toRefresh, toRefresh + '?k=' + key);
                // console.log('Force refresh on cached script files. From: ' + aScript.src + ' to ' + new_src)
                aScript.src = new_src;
            }
        }
    }
}

3

如果您使用的是php可以做到:

 <script src="js/myscript.js?rev=<?php echo time();?>"
    type="text/javascript"></script>

5
这个问题不仅在四年前问过,而且即使没有被接受,它的回答也更好。

3
同样,此方法将每次都重新下载文件,而不管实际的修订号或对文件进行的更改如何,这将完全禁用缓存。
Antti29年


2

请不要提供不正确的信息。 缓存api是与http缓存不同的缓存类型

服务器发送正确的标头时会触发HTTP缓存,您无法使用javasvipt访问。

另一方面,您会在需要时触发缓存api,与服务工作者一起使用时它很有用,因此您可以将请求与此类缓存相交并进行响应,请参阅:ilustration 1 ilustration 2 课程

您可以使用以下技术在您的用户上始终拥有新鲜的内容:

  1. 使用location.reload(true)这对我不起作用,因此我不建议这样做。
  2. 使用Cache API以便保存到缓存中并与Service Worker相交,请小心这一点,因为如果服务器发送了缓存头要刷新的文件,浏览器将首先从HTTP缓存中进行应答,如果找不到它,它将进入网络,因此您可能会得到旧文件
  3. 从您的stactics文件中更改url,我的建议是您应该使用文件内容的更改来命名它,我使用md5,然后将其转换为对字符串和url友好的文件,md5会随着文件内容的变化而变化,在那里可以自由发送HTTP缓存头足够长的时间

我建议第三位看到


1

我倾向于对框架进行版本控制,然后将版本号应用于脚本和样式路径

<cfset fw.version = '001' />
<script src="/scripts/#fw.version#/foo.js"/>

3
OP没有提到Coldfusion。
marctrem 2014年

@VijayDev 404 for your link
smarber

1
window.parent.caches.delete("call")

在控制台中执行代码后,关闭并打开浏览器。


1
请进行一些解释,以上代码中的“调用”是什么?
阿南·洛克兹(Annand Rockzz)'17

@AnandRockzz是不可能的,高速缓存api只是可以使用javascipt管理的一种新型高速缓存,因此为了从此处删除某些内容,您已经保存了它,然后再查看developer.mozilla.org/en-US/docs/网络/ API /缓存
约翰Balvin阿里亚斯

1

您也可以使用元HTML标记禁用浏览器缓存,只需将html标记放在开头部分,以避免在进行编码/测试时缓存网页,完成后就可以删除元标记。

(在头部)

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0"/>

将其粘贴到头部后刷新页面,并且也应该刷新新的javascript代码。

如果需要,此链接将为您提供其他选择 http://cristian.sulea.net/blog/disable-browser-caching-with-meta-html-tags/

或者你可以像这样创建一个按钮

<button type="button" onclick="location.reload(true)">Refresh</button>

它会刷新并避免缓存,但是它将在您的页面上显示直到完成测试,然后您才能将其删除。拳头选项是我最好的东西。


1

导致浏览器缓存相同的链接,您应该在网址末尾添加一个随机数。 new Date().getTime()产生一个不同的数字。

只需new Date().getTime()像呼叫一样添加链接的结尾

'https://stackoverflow.com/questions.php?' + new Date().getTime()

输出: https://stackoverflow.com/questions.php?1571737901173


欢迎来到SO!您的答案不清楚。请编辑它。基于链接的此类回复应予以评论,以防万一链接消失。
DavidGarcíaBodego,

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.