4

Im having trouble with caching...

Im using this php file with url rewriting to compress and cache css and js

I was under the impression that if i changed/updated one of my files, that the browser would retrieve the updated file. But it doesnt unless i clear the cache or refresh the page.

Is my coding wrong? Or is the browser not suppose to get updated content until the cache expiration period has expired?

<?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");
}
?>

rewrite rules

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]    

---------

EDIT: Maybe i should be doing this a different way? what do the big companys use to cache, and how do they force browsers to get the updated content before the cache is set to expire?

EDIT 2: Thanks guy for the help. Im going with a 1 hour cache

3 Answers 3

6

The Browser doesn't refresh cached files until the given Expires header expired. If it's expired, it will request the file with an If-None-Match header (I guess).

But why didn't you handle cache control via .htaccess? You could check mod_expires:

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

# ETag
FileETag All

Gzip compression as well with mod_deflate:

AddOutputFilterByType DEFLATE text/css application/javascript

Edit: 'Big companies' don't use Expires or max-age headers, or they will set these headers to let cache files for ~1 hour -> conflicts with caching will be minimized. You're setting it to 1 week.

Sign up to request clarification or add additional context in comments.

1 Comment

Im using II7 and a url rewrite from helicontech
1

You missing these part, i believe...

    $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...

btw, for helping you determine, much more, related how your cache performance, or even better, your whole app performace, you can test it by using Google API performance, or these sites : http://www.webpagetest.org/ (PS: just for example, these is my latest result for my on working blog : http://www.webpagetest.org/result/110803_SB_17PVH/)

2 Comments

I think i already have that part, just done differently from how you did it
if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] == gmdate('D, d M Y H:i:s \G\M\T', $last_modified)) is the missing piece.
0

Yes, in theory the browser should pay attention to the Cache-Control, Expires, etc. information you're sending back, but in practice it's not always a good idea to trust the browser to do the right thing.

What you might want to consider doing is adding a second step in your compress.php script ... have it do a redirect to the actual compressed file, and append something like "?ts=".$last_modified_time to the path to the file. That way the URL will change when the file changes, and the browser will be much more likely to do the right thing and get the most recent file. I've used a similar technique before.

1 Comment

I dont really want to use redirects :/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.