4

缓存有问题...

我使用这个带有 url 重写的 php 文件来压缩和缓存 css 和 js

我的印象是,如果我更改/更新了我的一个文件,浏览器将检索更新的文件。但除非我清除缓存或刷新页面,否则它不会。

我的编码错了吗?或者浏览器不应该在缓存到期之前获取更新的内容?

<?php
$file = $_SERVER['DOCUMENT_ROOT'].'/'.$_GET['file'];
$last_modified_time = filemtime($file);
$etag = md5_file($file);
$expires = 60*60*24*7;

if(file_exists($file))
{
    if($_SERVER['HTTP_IF_NONE_MATCH'] != $etag)
    {   
        header("Pragma: public");
        header("Cache-Control: maxage=$expires, must-revalidate");
        header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT');
        header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT");
        header("Etag: \"{$etag}\"");

        if($_GET['type'] == 'js')  header('Content-type: application/javascript');
        if($_GET['type'] == 'css') header('Content-type: text/css');
        if($_GET['type'] == 'ico') header('Content-type: image/x-icon');

        ob_start("ob_gzhandler");       
        include($file);     
    }
    else {

        header('HTTP/1.0 304 Not Modified');
    }
}
else {

    header("HTTP/1.0 404 Not Found");
}
?>

重写规则

RewriteRule ^(.*).js$ /compress.php?file=$1.js&type=js [L,QSA]
RewriteRule ^(.*).css$ /compress.php?file=$1.css&type=css [L,QSA]
RewriteRule ^(.*).ico$ /compress.php?file=$1.ico&type=ico [L,QSA]    

---------

编辑:也许我应该以不同的方式做这件事?大公司用什么来缓存,他们如何强制浏览器在缓存设置过期之前获取更新的内容?

编辑2:谢谢家伙的帮助。我要使用 1 小时的缓存

4

3 回答 3

6

Expires在给定的标头过期之前,浏览器不会刷新缓存的文件。如果它已过期,它将请求带有If-None-Match标题的文件(我猜)。

但是你为什么不通过 处理缓存控制.htaccess?你可以检查mod_expires

# Expires-Header
ExpiresActive On
ExpiresByType application/javascript "access plus 7 days"
ExpiresByType text/css "access plus 7 days"

# ETag
FileETag All

Gzip 压缩以及mod_deflate

AddOutputFilterByType DEFLATE text/css application/javascript

编辑:“大公司”不使用Expiresormax-age标头,否则他们将设置这些标头以让缓存文件约 1 小时-> 与缓存的冲突将被最小化。您将其设置为 1 周。

于 2011-08-03T20:42:47.110 回答
1

你错过了这些部分,我相信......

    $last_modified = filemtime($file);

    // Check for cached version
    if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) OR isset($_SERVER['HTTP_IF_NONE_MATCH'])) 
    {
        // these part should do that...
        if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] == gmdate('D, d M Y H:i:s \G\M\T', $last_modified)) 
        {
            header('HTTP/1.0 304 Not Modified');
            return;
        }
    }   
    header('Last-Modified : '.gmdate('D, d M Y H:i:s \G\M\T', $last_modified));
    header('Cache-Control : max-age='.$expires.', must-revalidate');
    header('Expires : '.gmdate('D, d M Y H:i:s \G\M\T', $last_modified + $expires));
    // and so on...

顺便说一句,为了帮助您确定更多有关您的缓存性能,甚至更好的是您的整个应用程序的性能,您可以使用 Google API 性能或以下站点对其进行测试:http ://www.webpagetest.org/ ( PS:例如,这是我在工作博客上的最新结果:http ://www.webpagetest.org/result/110803_SB_17PVH/ )

于 2011-08-03T20:50:29.673 回答
0

是的,理论上浏览器应该注意你发回的 , 等信息,但在实践中,相信浏览器做正确的事情并不总是一个好主意Cache-ControlExpires

您可能想要考虑做的是在您的 compress.php 脚本中添加第二步...让它重定向到实际的压缩文件,并将类似的内容附加"?ts=".$last_modified_time到文件的路径中。这样,当文件更改时,URL 将发生更改,并且浏览器将更有可能做正确的事情并获取最新的文件。我以前使用过类似的技术。

于 2011-08-03T20:35:59.053 回答