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 allows the browser to load previously downloaded resources from local disk rather than over the network.
HTTP supports local caching of static resources by the
browser.
However, unless the web
server
indicates that a resource can be cached, the browser may
assume that the resource is not cacheable, and re-request on every
visit to a page. To take advantage of the full benefits of caching, you
need to instruct your web server to 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 possibleFor 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 remoter 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.