# 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