缓存通过params破坏

Bra*_*man 113 html javascript css caching

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

<link rel="stylesheet" href="base_url.com/file.css?v=1.123"/>
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*all 107

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

并且,浏览器将假定下次调用时源将保持不变,?v=1.123使用该字符串缓存它.因此它将保持缓存状态,但是您的服务器已设置,直到您移动到?v=1.124等等.

  • 这篇博文现在已经接近十年了.您认为缓存提供商和CDN还没有适应它吗?Squid似乎能够使用查询字符串[now]来缓存文档(http://serverfault.com/questions/401201/squid-cannot-cache-static-files-with-query-string/401205). (25认同)
  • 引用Steve Souders:"为了获得流行代理缓存的好处,请避免使用查询字符串进行加速,而是修改文件名本身." 完整的解释可以在这里找到:http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/ (4认同)

Pek*_*ica 36

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

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

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

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

  • @spender我已经读过一些代理服务器(旧的,或者可以配置为)在缓存时忽略查询字符串. (2认同)
  • @spender - 我听说过同样的,我认为改变文件名,或者路径是最好的选择.将所有静态文件移动到版本化文件夹名称下可能是最容易的,例如`/ static/v22/file.css`,因为你可以用一个文件夹重命名来做多个文件,例如`/ static/v23/file.css`和`/ static/v23/mystuff.js` (2认同)

jfr*_*d00 22

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

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

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

  • 我同意如果你想 10000% 确定的话,将版本号放在文件名中是最终最安全的解决方案,但我不遵循“同时存在多个版本”的论点。具有查询参数的 URL 与具有不同查询参数的同一 URL 不同。客户应将它们视为两种不同的资源;如果不是,客户端就坏了。 (2认同)
  • @Pekka - 版本号可以允许一次存在多个版本,但这需要服务器合作将查询参数映射到正确的实际文件.我不认为这是OP在这里做的事情,并且没有理由要求在修改文件名时更复杂,并且不需要服务器合作.显然两者都可以奏效. (2认同)

has*_*nge 11

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

也就是说,在我所看到的引用来源的建议中,所有人似乎都从史蒂夫·索德斯的一篇2008年的文章中汲取了他们的智慧.他的结论是基于当时代理人的行为,他们现在可能相关或不相关.但是,在没有更多当前信息的情况下,更改文件名是安全的选择.


ncr*_*ins 9

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

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


Ken*_*Liu 6

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

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


Bob*_*ack 5

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

  • Steve Souders文章中引用的squid代理已更改其默认缓存策略.从版本2.7(2008年5月)和版本3.1(2010年3月)开始,默认行为是缓存动态内容. (5认同)

use*_*ser 5

发现2项技术的比较(查询字符串VS文件名)在这里:

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

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

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