缓存控制问题

时间:2010-09-29 09:49:53

标签: apache optimization .htaccess caching

如果我在我的网站上设置此缓存控制:

Header unset Pragma
FileETag None
Header unset ETag

# 1 YEAR
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|swf|mp3|mp4)$">
Header set Cache-Control "public"
Header set Expires "Thu, 15 Apr 2010 20:00:00 GMT"
Header unset Last-Modified
</FilesMatch>

# 2 HOURS
<FilesMatch "\.(html|htm|xml|txt|xsl)$">
Header set Cache-Control "max-age=7200, must-revalidate"
</FilesMatch>

# CACHED FOREVER
# MOD_REWRITE TO RENAME EVERY CHANGE
<FilesMatch "\.(js|css)$">
Header set Cache-Control "public"
Header set Expires "Thu, 15 Apr 2010 20:00:00 GMT"
Header unset Last-Modified
</FilesMatch>

...那么如果我更新任何css或图像或其他文件,用户浏览器是否仍然会使用缓存版本直到它过期(一年后)?

由于

2 个答案:

答案 0 :(得分:1)

是的,将来response with an expiration date将被认为是新鲜的:

  

Expires entity-header字段给出了响应被视为过时的日期/时间。 [...]

     

除非在Cache-Control标头字段中另有说明,否则在将来默认情况下不可缓存的响应的日期值为某个时间的Expires头字段的存在表示该响应是可缓存的( section 14.9)。

请注意,将来超过一年的到期日期可能会被解释为永不过期

  

要将响应标记为“永不过期”,原始服务器会在发送响应后大约一年内发送过期日期。 HTTP / 1.1服务器不应该在未来发送超过一年的过期日期。

因此,如果缓存存储了响应,即使没有在发送缓存之前重新验证缓存的响应,它也可能会从缓存中获取响应。

现在,如果您更改的资源是already stored in caches and still fresh, there is no way to invalidate them

  

[...]虽然它们可能会继续“新鲜”,但它们并不能准确反映原始服务器为该资源上的新请求返回的内容。

     

HTTP协议无法保证所有此类缓存条目都标记为无效。例如,在原始服务器上导致更改的请求可​​能没有通过存储缓存条目的代理。

这就是为什么这种永不过期的资源使用URL中的唯一版本号(例如style-v123.css)的原因,该版本号随每次更新而更改。这也是我在这种情况下的建议。

顺便说一句,在这种情况下,用Cache-Control as public声明响应并没有做任何事情。仅当需要授权的响应可以缓存时才使用此选项:

  

public - 表示任何缓存都可以缓存响应,即使它通常只在非共享缓存中不可缓存或可缓存。 (有关其他详细信息,另请参阅授权section 14.8。)

有关HTTP缓存的更多信息:

答案 1 :(得分:1)

您的css,js和图片文件永远不会被缓存,因为您在过去设置日期。

我认为这是一个错误,并且您打算将其设置为未来一年,这是支持max-age超过期限的一个原因。

如果是这种情况,那么您的图片将被缓存一年。允许随时从缓存中删除某些内容,例如清除不常使用的条目以减少缓存占用的磁盘大小。

有两种可能的方法来处理降低陈旧风险的可能性。一种是设置一个低得多的到期时间,并使用电子标签和修改日期,以便在过期时间过后,如果没有变化,你可以发送304,所以服务器只需要发送几个字节而不是整个实体。

另一种方法是保持一年的到期时间,但要更改更改时使用的URI。这在例如情况下是有用的。一个大型文件,几乎在您网站的每个页面上使用。它要求您在更改时更改对该资源的所有引用(因为您实际上正在更改为使用新资源),这可能是繁琐的,因此仅建议在少数热点情况下进行优化。如果文件忽略了查询属性(例如,它只是直接从文件中提供),浏览器就不会知道,因此您可以使用类似/scripts/bigScript.js?version=1.2.3的内容,然后在更改bigScript.js时更改为/scripts/bigScript.js?version=1.2.4 。这对bigScript.js没有影响,但会导致浏览器获取一个新文件,因为它知道它是一个完全不同的资源。