Which headers should I use for serving static content?
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 t开发者_StackOverflow中文版o 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.)
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.
See:
- Multiple javascript/css files: best practices?
- Supercharging Javascript in PHP; and
- Supercharging CSS in PHP;
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.
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).
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.
精彩评论