缓存 CSS 和 JavaScript

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小时的缓存时间。

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

使用mod_deflate进行Gzip压缩:

AddOutputFilterByType DEFLATE text/css application/javascript

编辑:'大公司' 不使用 Expiresmax-age 头,或者他们将设置这些头让缓存文件保留约1小时 -> 可以最小化缓存冲突。你把它设置为1周。

我正在使用II7和来自helicontech的URL重写。 - tuurbo

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/


我想我已经有了那一部分,只是和你做的方式不同。 - tuurbo
if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] == gmdate('D, d M Y H:i:s \G\M\T', $last_modified)) 是缺失的部分。 - toopay

0

理论上,浏览器应该注意您发送回来的Cache-ControlExpires等信息,但实际上信任浏览器做正确的事情并不总是一个好主意。

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


我真的不想使用重定向 :/ - tuurbo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接