Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caching gzipped css

Tags:

html

css

php

gzip

I've got over some tutorials on how to gzip a css file in which you create a public php file to include css files with compression. The problem is I cannot get it to cache my css files. I'm using firebug for reference and I've actually tried using the same code to compress some javascript and it caches it fine.

Here is the code:

if(extension_loaded('zlib')){
ob_start('ob_gzhandler');
}
$offset = 60 * 60 * 24 * 31;
header('Content-type: text/css');
header ('Cache-Control: max-age=' . $offset . ', must-revalidate');
header ('Expires: ' . gmdate ("D, d M Y H:i:s", time() + $offset) . ' GMT');
ob_start("compress");
function compress($buffer) {
    // Remove Comments, White Space, End ;'s
    $buffer = preg_replace('#/\*.*?\*/#s', '', $buffer);
    $buffer = preg_replace('/\s*([{}|:;,])\s+/', '$1', $buffer);
    $buffer = preg_replace('/\s\s+(.*)/', '$1', $buffer);
    $buffer = str_replace(';}', '}', $buffer);
    $buffer = str_replace(' {', '{', $buffer);
    return $buffer;
    }

    include('global.css');

    if(extension_loaded('zlib')){
    ob_end_flush();
}

Then I'm simply referencing my php file as a css document on other pages. As you can see I've tried adding max age to the mix which also proves unsuccessful.

Here are the response headers

Date    
Tue, 21 Jul 2009 19:59:19 GMT

Server  
Apache/1.3.41 (Darwin) PHP/4.4.9

X-Powered-By    
PHP/4.4.9

Cache-Control   
max-age=2592000, must-revalidate

Expires 
Thu, 20 Aug 2009 19:59:19 GMT

Content-Encoding    
gzip

Vary    
Accept-Encoding

Keep-Alive  
timeout=15, max=93

Connection  
Keep-Alive

Transfer-Encoding   
chunked

Content-Type    
text/css

Is there anything I'm missing, or a better way to go about doing this?

Thanks,

EDIT:

A script that detects whether or not the file has been changed & sending a 304 if it hasn't, in combination with proper headers has solved this problem.

Arthur

like image 607
askon Avatar asked Jul 21 '09 19:07

askon


1 Answers

Try adding this to the set of headers:-

$offset = 60 * 60 * 24;
header('Content-type: text/css');
header('Cache-Control: max-age=' . $offset);
header('Expires: ' . gmdate ("D, d M Y H:i:s", time() + $offset) . ' GMT');
header('Last-Modified: ' . gmdate ("D, d M Y H:i:s", time()) . ' GMT');

The problem was the must-revalidate instruction in the cache control header. This would cause the client to re-request the css each time it is needed and your code has no handling for the If-Modified-Since header and the sending of a 304 Unmodified response status code.

The above approach reduces the cache period to 1 day and eliminates the must-revalidate instruction. It also adds the Last-Modified header (a cache may choose not to cache an item when a Last-Modified or ETag header is missing).

To improve this you could find the actual last modified time of the css file you are compressing and send that as the Last-Modified header. You could include in your code a comparison of the requests If-Modified-Since header with the value of the css files last modified time. If you find them the same send this set of headers but also send a 304 Unmodfied status and don't send the body at all. (I'm not really a PHP person so I'll leave that to the PHP experts to place in another answer).

Make a realistic assessment of how long you would want a client cache the css before it must make another attempt to retrieve it and set the max-age value accordingly.

like image 120
AnthonyWJones Avatar answered Oct 12 '22 23:10

AnthonyWJones