# NOTE: For every MIME type added to the mod_expires section, add the appropriate file extension in the # mode_headers section of browser and proxy caching. Conversely, for every file extension added to the # mod_headers section (either in the browser or proxy caching section), add the appropriate MIME type in # the mod_expires section of browser caching. # Enabling filename rewriting (file.XXX.ext) if URL rewriting is enabled # Otherwise URLs will use query strings (file.ext?v=XXX) # # More proxies cache assets if there is no query string # RewriteEngine On # Setting up an environment variable so your code can detect if mod_rewrite rules are executable # in this folder and you can use file.123.jpg or you need to fall back to file.jpg?123 RewriteRule . - [E=URLVERSIONREWRITE:YES] # Rewrites a version in file.123.jpg as well as timestamped version file.123_m_12345123512354.jpg # to original file.jpg so you can use it instead of file.jpg?123 which isn't cached in some proxies. RewriteRule ^(.*)\.(\d+)(_m_\d+)?\.([^\.]+)$ $1.$4 [L,QSA] #====================================================================================================== # Compression: http://code.google.com/speed/page-speed/docs/payload.html#GzipCompression #====================================================================================================== # TODO: set a minimum file size to compress (e.g. 1K), if possible # TODO: set caching for compression, if possible # Applications AddOutputFilterByType DEFLATE application/atom+xml AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/json AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE application/xml # Texts AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/x-component AddOutputFilterByType DEFLATE text/xml #====================================================================================================== # Browser Caching: http://code.google.com/speed/page-speed/docs/caching.html#LeverageBrowserCaching #====================================================================================================== # Google recommends specifying the following for all cacheable resources: # # 1. Expires or Cache-Control max-age # # Set Expires to a minimum of one month, and preferably up to one year, in the future. (We # prefer Expires over Cache-Control: max-age because it is is more widely supported.) Do not # set it to more than one year in the future, as that violates the RFC guidelines. # # 2. Last-Modified or ETag # # Set the Last-Modified date to the last time the resource was changed. If the Last-Modified # date is sufficiently far enough in the past, chances are the browser won't refetch it. # # Per Google: "It is redundant to specify both Expires and Cache-Control: max-age, or to specify # both Last-Modified and ETag." # # Steve Saunders, author of High Performance Web Sites: Essential Knowledge for Front-End Engineers, # points out that RFC 2616 suggests servers should not set an Expires date more than a year in the # future. However, he further points out that this is merely a guideline. # # See: http://developer.yahoo.com/blogs/ydn/posts/2007/05/high_performanc_2/. Yahoo uses an agressive, # 10 year, far future expires header. Let's do the same. ExpiresActive On # Applications ExpiresByType application/javascript "access plus 10 years" ExpiresByType application/json "access plus 10 years" ExpiresByType application/pdf "access plus 10 years" ExpiresByType application/x-shockwave-flash "access plus 10 years" ExpiresByType application/xml "access plus 10 years" # Images ExpiresByType image/bmp "access plus 10 years" ExpiresByType image/gif "access plus 10 years" ExpiresByType image/jpeg "access plus 10 years" ExpiresByType image/png "access plus 10 years" ExpiresByType image/tiff "access plus 10 years" ExpiresByType image/vnd.microsoft.icon "access plus 10 years" # Texts ExpiresByType text/css "access plus 10 years" ExpiresByType text/plain "access plus 10 years" ExpiresByType text/x-component "access plus 10 years" ExpiresByType text/xml "access plus 10 years" # Videos ExpiresByType video/x-flv "access plus 10 years" # Per Google: "It is redundant to specify both Expires and Cache-Control: max-age, or to specify # both Last-Modified and ETag." # We have already specified Expires, so let's unset Cache-Control # TODO: remove just "max-age", if possible (perhaps using "edit") Header unset Cache-Control # Apache will set Last-Modified based on the resource's date, so let's unset ETag Header unset ETag # Per Google: "In general, HTML is not static, and shouldn't be considered cacheable." Header set Expires "Thu, 01 Jan 1970 00:00:00 GMT" # TODO: Google.com's setting are the following # Expires -1 # Cache-Control private, max-age=0 # # Per Google: "Internet Explorer does not cache any resources that are served with the Vary header # and any fields but Accept-Encoding and User-Agent. To ensure these resources are cached by IE, # make sure to strip out any other fields from the Vary header, or remove the Vary header altogether # if possible" # TODO: test this #BrowserMatch "MSIE 4\.0" force-no-vary #BrowserMatch "MSIE 5\.0" force-no-vary #BrowserMatch "MSIE 6\.0" force-no-vary #BrowserMatch "MSIE 7\.0" force-no-vary # # TODO: # Some versions of Firefox require that the Cache control: public header to be set in order for resources # sent over SSL to be cached on disk, even if the other caching headers are explicitly set. Although this # header is normally used to enable caching by proxy servers (as described below), proxies cannot cache # any content sent over HTTPS, so it is always safe to set this header for HTTPS resources. #====================================================================================================== # Proxy Caching: http://code.google.com/speed/page-speed/docs/caching.html#LeverageProxyCaching #====================================================================================================== # Per Google: "Use the Cache-control: public header to indicate that a resource can be cached by public # web proxies in addition to the browser that issued the request." Header set Cache-Control "public" # Per Google: "Don't enable proxy caching for resources that set cookies. Either set the Cache-Control # header to private or serve these resources from a cookieless domain." Header set Cache-Control "private" # Per Google: "Some public proxies have bugs that do not detect the presence of the Content-Encoding # response header. This can result in compressed versions being delivered to client browsers that # cannot properly decompress the files. Since these files should always be gzipped by your server, to # ensure that the client can correctly read the files, do either of the following:" # Ideal for multi-homed applications # Header set Cache-Control "public" # Ideal for singly homed applications Header set Vary "Accept-Encoding" # http://developer.yahoo.com/performance/rules.html#etags FileETag None # Set default character set AddDefaultCharset UTF-8