如何正确设置css / js静态caching

为了防止问题,当我更新CSS / JS媒体文件和浏览器不要求新版本,因为他们caching这些文件,我使用这个解决scheme: https : //github.com/jaddison/django-cachebuster ,增加?<文件的时间戳>到CSS / JS文件名(用/media/main.css?20012931203128replace/media/main.css。我认为它会迫使浏览器在更改时间戳(更新文件)时重新加载css文件,并使用本地caching版本但是我在Apache日志(和firebug)中看到的是,浏览器(至less是Firefox)在每次刷新页面时都会请求CSS / JS文件,即使获得了304代码,也可以看到来自日志的片段:

XXX.255.115.60 - - [24/Jul/2011:04:17:25 -0700] "GET /media/main.css?333900240611 HTTP/1.1" 304 172 "" "Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1" XXX.255.115.60 - - [24/Jul/2011:04:17:26 -0700] "GET /media/main.js?270101180511 HTTP/1.1" 304 173 "" "Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1" XXX.255.115.60 - - [24/Jul/2011:04:17:34 -0700] "GET /media/main.css?333900240611 HTTP/1.1" 304 172 "" "Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1" XXX.255.115.60 - - [24/Jul/2011:04:17:35 -0700] "GET /media/main.js?270101180511 HTTP/1.1" 304 173 "" "Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1" XXX.255.115.60 - - [24/Jul/2011:04:17:44 -0700] "GET /media/main.css?333900240611 HTTP/1.1" 304 172 "" "Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1" XXX.255.115.60 - - [24/Jul/2011:04:17:44 -0700] "GET /media/main.js?270101180511 HTTP/1.1" 304 173 "" "Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1" 

当然,这会让我的网站变慢。 是否有可能强制浏览器更新文件只有当.css?…之后的时间戳更改? 谢谢!

Upd:这是一个响应和请求的例子:

请求

 User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.2.18) Gecko/20110614 Firefox/3.6.18 Accept text/css,*/*;q=0.1 Accept-Language en-gb,en;q=0.5 Accept-Encoding gzip,deflate Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive 115 Referer DNT 1 Connection keep-alive If-Modified-Since Fri, 24 Jun 2011 05:39:33 GMT If-None-Match "8ed02f1-a21-4a66ea04f2f40" 

响应

 Date Sun, 24 Jul 2011 12:28:21 GMT Server Apache Connection Keep-Alive Keep-Alive timeout=2, max=99 Etag "8ed02f1-a21-4a66ea04f2f40" 

初始和响应

 Date Sun, 24 Jul 2011 12:51:05 GMT Server Apache Last-Modified Fri, 24 Jun 2011 05:39:33 GMT Etag "8ed02f1-a21-4a66ea04f2f40" Accept-Ranges bytes Content-Length 2593 Keep-Alive timeout=2, max=99 Connection Keep-Alive Content-Type text/css 

您应该使用适当的HTTP缓存指令来使响应永不过期 (将来一年):

 Cache-Control: max-age=31536000 Expires: Sun, 24 Jul 2012 12:51:05 GMT 

你可以在Apache中用mod_expires来做到这一点:

 ExpiresByType text/css "now plus 1 year" ExpiresByType text/javascript "now plus 1 year" 

我玩了很多,我发现它可能是由Apache的错误引起的。 这不是浏览器的问题 – 一旦timesatmp在查询字符串中,浏览器就不能理解查询字符串,并且至少要询问服务器是否没有改变。 Apache响应良好,'304没有修改',但它总是发送文件!

我做了很多实验,唯一能解决问题的方法就是把时间戳直接放在文件名上 。 在PHP中,我使用以下函数:

 function safe_inline_url($file) { $basename = basename($file); if (strstr($basename, '.')) return dirname($file) . "/" . preg_replace('/(\.[^\.]*)$/', '_ts_' . filemtime($file) . '\1', $basename); else return $file . '_ts_' . filemtime($file); } 

修改任何内联网址(CSS,JS,图像,…),以便它添加时间戳,例如。 像js / forms.js => js / forms_ts_1278080148.js

在服务器上,您必须将修改过的文件名重新写回到真实名称,这是通过将这个名称放到您的.htaccess文件中完成的:

 RewriteEngine On RewriteCond %{REQUEST_URI} ^(.*)_ts_[0-9]{9,}$ RewriteRule ^ %1 [PT] RewriteCond %{REQUEST_URI} ^(.*)_ts_[0-9]{9,}\.(.*)$ RewriteRule ^ %1.%2 [PT] 

你把它放到根目录下,你也必须把它放到RewriteEngine On的每个子目录的.htaccess

唯一的问题是使用URL来包含其他来源的scriptaculous JavaScript库 – 你不能使用这个技巧来包含他们的js文件。