2

I am using gzip on my css to compress on page load. To do this I have made my css (stylesheet.css.php) file.

This is my PHP script included inside file :

<?php
   ob_start ("ob_gzhandler");
   header ("content-type: text/css; charset: UTF-8");
   header ("cache-control: must-revalidate");
   $offset = 60 * 60;
   $expire = "expires: " . gmdate ("D, d M Y H:i:s", time() + $offset) . " GMT";
   header ($expire);
?>
/*css stuff*/

I understand that the ($offset = 60 * 60;) is "sending an 'Expires' header, to set an age on how long our cached file will last. Here we set it to expire in one hour."

My problem is obviously if it expires every hour and I change a CSS setting it wont update until an hour, thus giving a user un-updated stylesheet? How do I change it to say update every one min so it fetches an updates stlyesheet every minute not hour? Would I just put ($offset = 60;) meaning 1 second?

My other problem is in internet explorer when I use HTTPS and say user hits back button IE gives message "do you want to view only the webpage content that was delivered securely" and you can click 'Yes' or 'No'. If you click 'No' then the CSS does not get loaded on that previous page. I am accessing my CSS using link href='/css/stylesheet.css' path format so cant see why its not secure? Thanks

daza166
  • 3,543
  • 10
  • 35
  • 41

3 Answers3

1

You can't do that.

Expire is meant to don't make an additional request by the client.
You will have to wait 1hour to be sure that all user cache are flushed.

The dirty way is to append a param whenever you change your css.

Something like:

style.css?param=123 
dynamic
  • 46,985
  • 55
  • 154
  • 231
1

To shorten the time the clients wait before requesting the file again, you can shorten your 'offset' like you said. The unit the time() function uses is seconds, so '60' would mean one minute. If you update your css regularly, maybe you should not use the expires header at all to save you the hassle, since most clients automatically cache css files.

There are two solutions for the https problem. Either you check if the request comes in via http oder https and write the url for your css file accordingly, or you use just //folder/path/to/cssfile.php as the path to your css file. Note the 2 slashes and the absence of 'http'. This notation automatically gives you the right protocol, like here.

Community
  • 1
  • 1
svanelten
  • 473
  • 2
  • 14
1

What you are suggesting is a bad idea. The way you want to set it up will totally break all caching of your CSS file and have you regenerating it on the fly for every request.

It is definitely a best practice to serve gzipped files, the problems are the way you're doing it. First, hitting the PHP interpreter and gzipping on the fly on every request is very bad for performance and more than negates the benefit of serving a compressed file. Plain HTTP file requests are going to be answered 10x faster than something than hits PHP.

The other issue is that, yes, you can reduce the expires time to 60 seconds (effectively, to zero ... but as svanelten says, at that point you might as well not send the header at all). There's no problem with not sending an expires header (or a short one) if that's really what you want, but doing this in combination with dynamically generating the page is bad if the content isn't actually changing that often. This breaks If-Modified-Since, which browsers send to make conditional requests so that they don't have to redownload the file if it hasn't changed. You are not setting a Last-Modified time so your last-modified time is effectively always "right now."

There are three ways to fix these problems (and accomplish your original goal of serving a compressed CSS file faster, in a cache-friendly way):

  1. Just enable gzip encoding in your web server's config and serve the CSS as a regular file. Then the web server handles everything. i.e. in Apache2, turn on mod_deflate.

  2. The next easiest way is to gzip the file and let your web server serve it. That way, the web server takes care of sending Last-Modified (which will just be the actual file modification time). And, it will send HTTP/304 Not Modified in response to conditional requests, so browsers don't have to re-download the file.

    For instance, if you are using Apache, you could just gzip the file and put in the same directory as your regular css file (so you have, for example, file.css and file.css.gz). Then put this into your Apache config or .htaccess:

    <Files *.css.gz>
      AddType "text/css" .gz
      AddEncoding gzip .gz
    </Files>
    
    RewriteEngine On
    RewriteCond %{HTTP:Accept-Encoding} gzip
    RewriteCond %{REQUEST_FILENAME}.gz -f
    RewriteRule ^(.*)$ $1.gz [QSA,L]
    
  3. The last way (if you must use PHP for this) is to have PHP cache the gzipped file, send the Last-Modified header for when the file was actually last modified, and respond to If-Modified-Since and If-None-Match requests by actually checking these things and then returning a 304 or 200 response accordingly. I do not recommend this because it still hits the PHP interpreter, and you are basically re-implementing webserver functions in PHP, but I've done it in special cases. It's the worst solution but at least better than dynamically generating everything.

joelhardi
  • 11,039
  • 3
  • 32
  • 38