根据Yahoo广为宣传的“加速站点最佳实践”,我们使用远期缓存过期标头提供来自CDN的静态内容。当然,我们有时需要更新这些“静态”文件,因此,我们目前在文件名中添加了一个中缀版本(基于文件内容的SHA1总和)。因此:

styles.min.css


成为:

styles.min.abcd1234.css


但是,管理版本化文件会变得很乏味,我想知道GET参数表示法是否会越来越好:

styles.min.css?v=abcd1234


您使用哪个,为什么?我应该考虑与浏览器或代理/缓存相关的注意事项吗?

评论

我问的原因是,我似乎想起了听到的一个不使用GET参数样式的原因,但是我不记得为什么。

使用GET参数不要求使用某种服务器端脚本来提供样式表(并且它将不再是静态的)吗?

@Lotus:您可以发送GET参数,如果什么都找不到,它们将被静默忽略。

#1 楼

根据Google的“使网络变得更快”,许多HTTP代理服务器都不会缓存带有查询参数的页面。 ?即使在响应中包含Cache-control: public标头,也不会在其网址中添加错误。要为这些资源启用代理缓存,请从对静态资源的引用中删除查询字符串,然后将参数编码为文件名本身。


因此,styles.min.abcd1234.css是首选解决方案。您可以使用适当的URL重写机制将styles.min.abcd1234.css透明地转换为易于实现的styles.min.css?v=abcd1234

如果仅支持HTTPS,则该建议将不适用,因为代理通常无法缓存所提供的页面通过SSL。

评论


我想知道有关查询字符串缓存和代理服务器的信息是否过时?在这种情况下,Google的文档不再引用查询字符串和代理服务器。尽管示例仍然涉及更改文件名本身。据报道,Squid 2.7(2008)和3.1(2010)默认情况下支持查询字符串缓存,并且可以配置早期版本来支持此功能。

–怀特先生
2015年10月25日,0:32

#2 楼

使用GET样式版本控制,从空白缓存中获取多个网址-例如style.css?v=123style.css?v=456-将返回相同的内容。但是我看不到这会有问题,尤其是因为您一次只能链接到一个。

我认为您会发现GET样式更易于维护。您不需要单独的文件:只需更改URL,浏览器就会重新获取CSS。

UPDATE:在进一步的研究中,似乎使用查询字符串可能会阻止浏览器缓存文件。但是,如果返回正确的标头(例如Expires),则这不是问题。

更新2:可接受的答案指出某些代理不缓存带有查询字符串的文件。但是,这是基于旧的信息。他们在Squid中提到的特定问题已在7年前解决。令人印象深刻的网站对此做了很好的记录。

评论


那是我要记住的警告。感谢您的链接。

–David Eyk
2010年11月8日,14:19

一种查询字符串有问题的方式:在服务器上,只有一个文件,但是任何查询字符串都是不同的URL。您在使用缓存时会使用版本控制,并且由于每个新版本都应该是不可变的,因此您将使用非常长的缓存。如果您使用的是反向代理,则某人有可能(尽管不太可能)通过获取尚未创建的版本来攻击您的服务器。例如。您只有style.css?v = 3,但是有人得到了style.css?v = 4。现在,该文件已缓存在反向代理中。当您上传第四个版本时,代理仍会提供先前缓存的第三个版本。

– OdraEncoded
20年6月1日19:39

@OdraEncoded您始终可以使用文件哈希作为查询字符串,因此无法猜测下一个版本。或在构建过程中使新查询字符串到期。

–心怀不满的山羊
20年6月2日,11:24

如果使用散列,它可能永远不会发生,但是从数学上来说并不是不可能的,并且使反向代理缓存无效会使项目更加复杂。恕我直言,最安全的方法是在请求不存在的版本时简单地返回404。没有必要在部署中返回存储在服务器中的最新版本(尽管在开发服务器中可能有意义),因此最简单的解决方案是在文件名而不是查询字符串中使用版本。

– OdraEncoded
20年6月3日,17:03



#3 楼

两者都可以正常工作,因为查询字符串被视为URL的一部分,并且通过更改它实际上是在更改资源名称,从而导致浏览器获取文件的新副本。

我说使用任何一种更易于维护的方法。