我们希望在生产部署中缓存失败,但不要浪费大量时间来确定系统。我的想法是使用当前版本号将cram和js文件的末尾应用一个参数:
<link rel="stylesheet" href="base_url.com/file.css?v=1.123"/>
两个问题:这会有效地打破缓存吗?这个参数是否会导致浏览器永远不会缓存来自该URL的响应,因为该参数表明这是动态内容?
答案 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)
在客户端下载资源之后,它会破坏缓存一次,除非客户端缓存中提供其他每个响应:
答案 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?
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>