Most web pages include resources that change infrequently, such as CSS files, image files, JavaScript files, and so on. These resources take time to download over the network, which increases the time it takes to load a web page. HTTP caching allows these resources to be saved, or cached, by a browser or proxy. Once a resource is cached, a browser or proxy can refer to the locally cached copy instead of having to download it again on subsequent visits to the web page. Thus caching is a double win: you reduce round-trip time by eliminating numerous HTTP requests for the required resources, and you substantially reduce the total payload size of the responses. Besides leading to a dramatic reduction in page load time for subsequent user visits, enabling caching can also significantly reduce the bandwidth and hosting costs for your site.
Setting an expiry date or a maximum age in the HTTP headers for static resources instructs the browser to load previously downloaded resources from local disk rather than over the network.
HTTP/S supports local caching of static resources by the browser. Some of the newest browsers (e.g. IE 7, Chrome) use a heuristic to decide how long to cache all resources that don't have explicit caching headers. Other older browsers may require that caching headers be set before they will fetch a resource from the cache; and some may never cache any resources sent over SSL.
To take advantage of the full benefits of caching consistently across all browsers, we recommend that you configure your web server to explicitly set caching headers and apply them to all cacheable static resources, not just a small subset (such as images). Cacheable resources include JS and CSS files, image files, and other binary object files (media files, PDFs, Flash files, etc.). In general, HTML is not static, and shouldn't be considered cacheable.
HTTP/1.1 provides the following caching response headers :
Expires and Cache-Control:
max-age.
These
specify the “freshness lifetime” of a resource, that is, the time
period during
which the browser can use the cached resource without checking to see
if a new
version is available from the web server. They are "strong caching
headers" that apply unconditionally;
that is, once they're set and the resource is downloaded, the browser
will not issue any GET requests for the resource until the expiry date
or maximum age is reached.Last-Modified and ETag.
These specify some characteristic about the resource that the browser
checks to determine if the
files are the same. In the Last-Modified
header, this is
always a date. In the ETag header, this can
be any value that uniquely identifies a resource (file versions or
content hashes are typical). Last-Modified is
a "weak" caching header in that the browser applies a heuristic to
determine whether to fetch the item from cache or not. (The heuristics
are different among different browsers.) However, these headers
allow the browser
to efficiently update its cached resources by issuing conditional
GET
requests when the user explicitly reloads the page. Conditional GETs
don't return the full
response unless the resource has changed at the server, and thus have
lower latency than full GETs.
It
is important to specify one of Expires
or Cache-Control max-age,
and one of Last-Modified
or ETag,
for all cacheable resources. It is
redundant to specify both Expires
and Cache-Control: max-age,
or to specify both Last-Modified
and ETag.
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.
If you know exactly when a resource is going to change, setting a shorter expiration is okay. But if you think it "might change soon" but don't know when, you should set a long expiration and use URL fingerprinting (described below). Setting caching aggressively does not "pollute" browser caches: as far as we know, all browsers clear their caches according to a Least Recently Used algorithm; we are not aware of any browsers that wait until resources expire before purging them.
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. 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 possibleCache control: public
directive to enable HTTPS caching for Firefox.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.
For the stylesheet used to display the user's calendar after login, Google Calendar embeds a fingerprint in its filename: calendar/static/fingerprint_keydoozercompiled.css, where the fingerprint key is a 128-bit hexadecimal number. At the time of the screen shot below (taken from Page Speed's Show Resources panel), the fingerprint was set to 82b6bc440914c01297b99b4bca641a5d:

The fingerprinting mechanism
allows the server to set the Expires header
to exactly
one year ahead of the request date; the Last-Modified
header to the date the file was last modified; and the Cache-Control:
max-age header to 3153600. To cause the client to
re-download the file in
case it changes before its expiry date or maximum age, the fingerprint
(and therefore the URL) changes whenever the file's content does.
Enabling public caching in the HTTP headers for static resources allows the browser to download resources from a nearby proxy server rather than from a remote origin server.
In addition to browser caching, HTTP provides for proxy caching, which enables static resources to be cached on public web proxy servers, most notably those used by ISPs. This means that even first-time users to your site can benefit from caching: once a static resource has been requested by one user through the proxy, that resource is available for all other users whose requests go through that same proxy. Since those locations are likely to be in closer network proximity to your users than your servers, proxy caching can result in a significant reduction in network latency. Also, if enabled proxy caching effectively gives you free web site hosting, since responses served from proxy caches don't draw on your servers' bandwidth at all.
You 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. With
some exceptions (described below), you should configure your web server
to
set this header to public for cacheable
resources.
Cache-control:
public header is present in the response. To enable proxy
caching for these resources, remove query strings from
references to static resources, and instead encode the parameters into
the file names themselves.
Cache-Control header
to private or serve these resources
from
a cookieless domain.
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:
Cache-Control header
to private.
This disables proxy caching altogether for these resources. If your
application is multi-homed around the globe and relies less on proxy
caches for user locality, this might be an appropriate setting.Vary: Accept-Encoding
response header. This instructs the proxies to cache two versions of
the resource: one
compressed, and one uncompressed. The correct version of the resource
is delivered based on the client request header. This is a good choice
for applications that are singly homed and depend on public
proxies for user locality.