在JavaScript中清除缓存

218

6
我感到困惑:"我们部署了最新的JavaScript代码,但我们无法获取最新的JavaScript代码。" - instanceof me
17
我猜你的意思是,如何强制客户端浏览器使用你的最新JavaScript版本而不是它们缓存的版本 - 如果是这种情况,你需要看Greg的回答。如果你想知道如何在你自己的浏览器中完成这个操作,那么看David Johnstone的回答即可。 - Benjol
1
https://dev59.com/tnVD5IYBdhLWcg3wAWoO - understack
5
一种常见的方法是在构建步骤中通过附加“?version=xxx”到你的JS链接文件。每次进行新的构建将请求JS文件的新版本。 - Ruan Mendes
1
@JuanMendes 这并不总是有效的。当人们尝试查看最新的网站图标时,建议执行相同的步骤。但这并不能保证一定有效。 - uSeRnAmEhAhAhAhAhA
显示剩余2条评论
23个回答

240

更新:有关此非标准参数的背景以及Firefox如何成为唯一支持该参数的现代浏览器,请参见location.reload()没有参数


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

然而,您最好的策略是按照其他答案中提到的版本化路径或文件名。此外,请参见Revving Filenames: 不要使用查询字符串,了解不使用?v=n作为您的版本控制方案的原因。


6
哇,谢谢!这对于从cache.manifest文件加载的HTML5应用程序缓存也很有效。我有一个旧的清单没有被从内存中删除,所以一个已经缓存了它的浏览器就无法显示更新的文件。我在JavaScript控制台中输入了这个命令,而且运行得很好。谢谢! - JayCrossler
2
但是通过更改文件名来提高版本号,不会让之前的所有版本都保留在原地吗?否则,搜索引擎等将会尝试读取旧版本(或书签/链接图像),导致大量失败的尝试。 - Rodolfo
1
这和用户点击刷新按钮是一样的吗? - Sam YC
2
@Manuel 它只会禁用从缓存访问您调用location.reload(true)的确切URL的页面。它从不清除原始页面的缓存,因为它只是向新请求附加时间戳,如果此页面异步地进行其他调用,则这些请求将不会禁用其缓存行为。例如,如果您使用reload(true)刷新加载某些HTML的页面,并且该页面具有脚本,使第二个ajax调用以在同一页上显示更多HTML,则第二个请求将不会禁用其缓存。 - J. Schei
3
Reload(true)已经被弃用了,不幸的是。 - ataraxis
显示剩余6条评论

124

你无法使用javascript清除缓存。

一种常见的方法是将修订号或最后更新时间戳附加到文件末尾,像这样:

myscript.123.js

或者

myscript.js?updated=1234567890


9
请注意,许多代理服务器在文件包含查询字符串时将无法缓存该文件。请参见 Kevin Hakanson 的回答 - chiborg
6
当整个 HTML 页面被缓存时,如何清除缓存?即使加入版本号也无效,因为 HTML 被缓存了。请帮忙。 - Nandakumar
如果我无法清除缓存项,那么为什么MDN说我可以呢?我错过了什么吗?我尝试了MDN所说的方法,但没有成功。 - Sнаđошƒаӽ

48

尝试更改JavaScript文件的src属性?从这里开始:

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

变成:

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

这个方法应该会强制你的浏览器加载一个新的JS文件副本。


1
n=1是什么作用? - KyelJmD
1
它什么也不做,除了成为某个不同的东西。它可以是?12345或?Kyle。 - Oneezy
文件名也需要更改吗?还是只需要更改src路径? - Fred A
我从你那里得到了答案。 - AdDev

22

除了每小时或每周缓存一次,您可以根据文件数据进行缓存。

例如(在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文件执行此操作,但我不希望因此影响服务器速度。 - Colin Brogan
2
使用校验和是个好主意,但必须正确地进行。每次请求都计算每个文件的校验和会显著影响性能。查询字符串也不适合缓存,请参考其他回答。正确的做法是将校验和(部分?)或版本号附加到文件名后,并使用这个新名称(您可以使用构建脚本在部署时自动完成此操作)。请参考 gruntrevusemin - Frizi

11

您也可以在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"和"token"是什么意思? - Sam YC
4
@GMsoF 这只是一个额外的获取参数,它被用于(在这种情况下)告诉浏览器这是一个“不同”的文件。这样浏览器将会丢弃缓存版本并加载这个新的文件。这通常与文件的“最后修改日期”一起使用。希望这讲得清楚明白;-) - Jelmer

11

window.location.reload(true) 在HTML5标准中已被弃用。一种不使用查询字符串的解决方法是使用Clear-Site-Data头部,该头部正在标准化中。


这个解决方案,特别是在链接文章中列出的其他替代方法的支持下,是最好的选择。其他答案忽略了我们的用户已经有了缓存版本的文件,我们需要强制性地绕过这个缓存障碍。 - maninak

8
将以下代码放在您的模板结尾处:
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.length;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
      } 
   }
}

4
请提供翻译后的文本:请在您的解决方案中提供一些说明 - Gabriel Espinoza
@GabrielEspinoza 他使用JavaScript重新加载文件,以更新缓存。 - Neo Morina
当您循环遍历“torefreshs”时,请将for循环更改为for(var j=0;j<torefreshs.length;j++){ - Souvik Ray

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_contents从服务器读取js文件,然后在header中使用echo输出js内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接