缓存通过params破坏

时间:2012-03-13 21:45:01

标签: javascript html css caching

我们希望在生产部署中缓存失败,但不要浪费大量时间来确定系统。我的想法是使用当前版本号将cram和js文件的末尾应用一个参数:

<link rel="stylesheet" href="base_url.com/file.css?v=1.123"/>

两个问题:这会有效地打破缓存吗?这个参数是否会导致浏览器永远不会缓存来自该URL的响应,因为该参数表明这是动态内容?

12 个答案:

答案 0 :(得分:103)

参数?v=1.123表示查询字符串,因此浏览器会认为它是来自?v=1.0的新路径。因此导致它从文件而不是从缓存加载。如你所愿。

并且,浏览器会假设下次调用?v=1.123时<来源将保持不变,并且应该使用该字符串缓存它。因此,它将保持缓存状态,但是您的服务器已设置完毕,直到您转到?v=1.124左右。

答案 1 :(得分:35)

  

两个问题:这会有效地打破缓存吗?

是。 Even Stack Overflow use this method,虽然我记得他们(每天有数百万的访问者和数以万计的不同客户端和代理版本和配置)有一些奇怪的边缘情况,即使这还不足以打破缓存。但一般的假设是,这将起作用,并且是打破客户端缓存的合适方法。

  

param是否会导致浏览器永远不会缓存来自该URL的响应,因为param表明这是动态内容?

没有。该参数不会改变缓存策略;服务器发送的缓存标头仍然适用,如果它没有发送任何,则浏览器的默认值。

答案 2 :(得分:21)

将版本号放在实际文件名中更安全。这允许一次存在多个版本,因此您可以推出新版本,如果仍然存在请求旧版本的任何缓存HTML页面,他们将获得适用于其HTML的版本。

请注意,在互联网上任何一个最大的版本化部署中,jQuery使用实际文件名中的版本号,它可以安全地允许多个版本共存而无需任何特殊的服务器端逻辑(每个版本只是一个不同的文件)。

当您部署新页面和新链接文件(这是您想要的)时,这会破坏缓存一次,从那时起,这些版本可以被有效缓存(您也想要)。

答案 3 :(得分:11)

正如其他人所说,使用查询参数进行缓存清除通常被认为是一个坏主意(tm),并且已经存在了很长时间。最好在文件名中反映版本。 Html5 Boilerplate recommends against使用查询字符串等。

那就是说,我所看到的引用来源的建议,所有人似乎都是从史蒂夫·索德斯的2008 article中汲取灵感。他的结论是基于当时代理人的行为,这些天他们可能也可能不相关。但是,在没有更多当前信息的情况下,更改文件名是安全的选择。

答案 4 :(得分:9)

在客户端下载资源之后,它会破坏缓存一次,除非客户端缓存中提供其他每个响应:

  1. v参数已更新。
  2. 客户端清除其缓存

答案 5 :(得分:6)

一般来说,这应该没问题,但如果有一个配置为忽略请求参数的中间缓存(代理),则可能无法正常工作。

例如,如果您通过Akamai CDN提供静态内容,则可以将其配置为忽略请求参数,以防止使用此方法进行缓存清除。

答案 6 :(得分:5)

这在很大程度上取决于您希望缓存的强大程度。例如,squid代理服务器(可能还有其他)defaults to not caching URL使用查询字符串 - 至少,它是在编写该文章时执行的。如果您不介意某些用例导致不必要的缓存未命中,请继续查询参数。但是非常很容易设置基于文件名的缓存清除方案,避免了这个问题。

答案 7 :(得分:5)

找到了2种技术(查询字符串与文件名)here

的比较

作为查询字符串的版本有两个问题。

  

首先,它可能并不总是一个实现我们需要破解的缓存的浏览器。据说某些(可能是较旧的)代理确实忽略了查询字符串的缓存行为。

     

其次,在某些更复杂的部署方案中,您有多个前端和/或多个后端服务器,升级只是瞬间完成。您需要能够同时为资产的旧版本和新版本提供服务。例如,请参阅使用Google App Engine时这会对您产生的影响。

答案 8 :(得分:4)

另一种类似的方法是在提供文件时使用htaccess mod_rewrite忽略部分路径。永不缓存的索引页引用了文件的最新路径。

从开发的角度来看,就像使用params一样简单版本号,但它与文件名方法一样健壮。

使用路径的忽略部分作为版本号,服务器只是忽略它并提供未缓存的文件。

1.2.3/css/styles.css提供与css/styles.css相同的文件,因为第一个目录被剥离并被htaccess文件忽略

包括版本化文件

<?php
  $version = "1.2.3";
?>

<html>
  <head>
    <meta http-equiv="cache-control" content="max-age=0" />
    <meta http-equiv="cache-control" content="no-cache" />
    <meta http-equiv="expires" content="0" />
    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
    <meta http-equiv="pragma" content="no-cache" />
    <link rel="stylesheet" type="text/css" href="<?php echo $version ?>/css/styles.css">
  </head>
  <body>
    <script src="<?php echo $version ?>/js/main.js"></script>
  </body>
</html>

请注意,此方法意味着您需要禁用索引页面的缓存 - Using <meta> tags to turn off caching in all browsers?

.htaccess文件

RewriteEngine On

# if you're requesting a file that exists, do nothing
RewriteCond %{REQUEST_FILENAME} !-f 
# likewise if a directory that exists, do nothing
RewriteCond %{REQUEST_FILENAME} !-d 

# otherwise, rewrite foo/bar/baz to bar/baz - ignore the first directory
RewriteRule ^[^/]+/(.+)$ $1 [L] 

您可以在允许网址重写的任何服务器平台上采用相同的方法

(重写条件改编自mod_rewrite - rewrite directory to query string except /#!/

...如果您的索引页/网站入口点需要缓存清除,您可以随时use JavaSript刷新它。

答案 9 :(得分:2)

<script type="text/javascript">
// front end cache bust

var cacheBust = ['js/StrUtil.js', 'js/protos.common.js', 'js/conf.js', 'bootstrap_ECP/js/init.js'];   
for (i=0; i < cacheBust.length; i++){
     var el = document.createElement('script');
     el.src = cacheBust[i]+"?v=" + Math.random();
     document.getElementsByTagName('head')[0].appendChild(el);
}
</script> 

答案 10 :(得分:0)

 <script>
    var storedSrcElements = [
         "js/exampleFile.js",
         "js/sampleFile.js",
         "css/style.css"
          ];

    var head= document.getElementsByTagName('head')[0];
    var script;
    var link;
    var versionNumberNew = 4.6;

    for(i=0;i<storedSrcElements.length;i++){
     script= document.createElement('script');
     script.type= 'text/javascript';
     script.src= storedSrcElements[i] + "?" + versionNumberNew;
     head.appendChild(script);
    }     


     </script> 


       ### Change the version number  (versionNumberNew) when you want the new files to be loaded  ###

答案 11 :(得分:0)

希望这可以帮助您注入外部JS文件

<script type="text/javascript"> 
var cachebuster = Math.round(new Date().getTime() / 1000); 
document.write('<scr'+'ipt type="text/javascript" src="external.js?cb=' +cachebuster+'"></scr' + 'ipt>');
</script>

来源-Cachebuster code in JavaScript