views:

116

answers:

4

I am gzipping my static Javascript and CSS files using PHP. When the original file is requested, the server sends the Last-Modified and ETag headers. I'm not sending these with PHP just yet. I've also seen suggestions to use Cache-control and Expires headers and some more that I don't remember.

Are those first two enough? I guess I can get the last modified date quite easily with PHP, but how would I generate an ETag?

If it's better to include the other two, what's the best way to attach those to other files like images? Maybe through .htaccess? (I don't have direct access to the server.)

+1  A: 

for the ETag you can use any value, but I prefer to use the md5_file( ) sha1_file( ) of the current file[s] as a unique identifier for the content (shouldn't ever really have that many collisions).

Do this before any output.

<?php header( "Etag: " . sha1_file( basename( $_SERVER[ 'PHP_SELF' ] ) ) ); ?>

or you can let Apache do it for you in the .htaccess (if it is enabled, which is usually is):

# if we're clustered this will still be cool
FileETag MTime Size

And if you want to set a long expires (this is a little dangerous though), you can also do this:

# turn on far-future expiration dates
# to cache content longer (30 days)
ExpiresActive On
ExpiresDefault A2592000

But be careful, you'll have to make a version of the file () that you have to change every time you update the file.

Dan Beam
Can I do this for images only? Maybe using the `<Files>` directive? And how do you generate the code `A2592000`?
DisgruntledGoat
You can do this for only images, look up the apache command ExpiresByType (so you can do image/jpeg, for instance). So any type in your mime file (usually image/png, image/gif, image/jpeg) can be set to this. You could also do this on the <File> command as well, I guess, but by type seemed like a better solution to me (what if you use PHP images?). A2592000 is the number of seconds in a 30 days (do the math or trust me, :P)
Dan Beam
OK that gets the number, 2592000, why `A` at the front? Does that specify units or something?
DisgruntledGoat
`A` means time from access (when your browser last used it)
Dan Beam
+1  A: 

See:

Basically you want to:

  • Minimize the number of files you send (through combining them, spriting, etc);
  • Minify all Javascript files;
  • GZip everything (to browsers that correctly support it); and
  • Version everything.

By versioning I mean instead of:

<img src="/images/logo.gif">

add something to indicate a "version" like the mtime of the file:

<img src="/images/logo.gif?1234568899">

Combine this with a far future Expires header so the browser will only request the file once. Then when you want the browser to get a new copy you change the version number.

IMHO this is far superior to methods involving ETags and the like.

cletus
Thanks for the tips. Is there a way to automatically set an expires header for a few months after the current date? Looks like I can do `Header set Expires "Thu, 15 Apr 2010 20:00:00 GMT"` in the htaccess, but when that day draws near I'll have to put it forward a few months again...
DisgruntledGoat
A: 

Apache uses inode-size-timestamp as Etag this however does not work if you have a cluster of web servers. In this case you might use an md5 of url-size-timestamp. More info in the Etag section here

I would suggest not to calculate an md5 of the entire file because this might be expensive on large files (e.g. images, audio, video).

filippo
A: 

Why not use Apache directly to serve static requests?

It can compress stuff, as well as set headers correctly, and guess what, it handles edge-cases as well.

Handling conditional requests correctly isn't obvious and I don't think you should try to do it. Use a web server which already does it.

That said, not all of the defaults make sense. You should probably disable ETag if your site has more than one web server and setting an "Expires" header on infrequently-changing content is pretty much mandatory if you want clients' caches to be most useful.

Look at the somewhat condescending,

http://developer.yahoo.com/performance/rules.html

Which will help you.

MarkR