246

How to enable browser caching for my site? Do I just put cache-control:public somewhere up in my header like this?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
Cache-Control:public;
>

I am using the latest version of PHP developing on the latest version of XAMPP.

andrew
  • 4,758
  • 9
  • 40
  • 56
  • what server side language are you using? PHP?, ASP?, JSP? the way you set the headers is similar but not quite the same. Or if you are caching images... often this is done in your Apache (or web server) config – scunliffe Dec 18 '10 at 21:51
  • Sadly that "solution" simply generates an invalid DOCTYPE ;-) If you wish to do it from HTML (I wouldn't recommend it), you'd use [META HTTP-EQUIV](http://vancouver-webpages.com/META/metatags.detail.html) –  Dec 19 '10 at 03:54

8 Answers8

211

To use cache-control in HTML, you use the meta tag, e.g.

<meta http-equiv="Cache-control" content="public">

The value in the content field is defined as one of the four values below.

Some information on the Cache-Control header is as follows

HTTP 1.1. Allowed values = PUBLIC | PRIVATE | NO-CACHE | NO-STORE.

Public - may be cached in public shared caches.
Private - may only be cached in private cache.
No-Cache - may not be cached.
No-Store - may be cached but not archived.

The directive CACHE-CONTROL:NO-CACHE indicates cached information should not be used and instead requests should be forwarded to the origin server. This directive has the same semantics as the PRAGMA:NO-CACHE.

Clients SHOULD include both PRAGMA: NO-CACHE and CACHE-CONTROL: NO-CACHE when a no-cache request is sent to a server not known to be HTTP/1.1 compliant. Also see EXPIRES.

Note: It may be better to specify cache commands in HTTP than in META statements, where they can influence more than the browser, but proxies and other intermediaries that may cache information.

Community
  • 1
  • 1
Codemwnci
  • 51,224
  • 10
  • 90
  • 127
  • 38
    [HTML5 forbids this](http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#pragma-directives) and `` has always been a terrible and flaky way to specify caching. – Kornel May 02 '14 at 16:56
  • 2
    @porneL I have trouble understanding which part of your links forbids which part of the answer... the meta tag specs say nothing about disliking what's written here, or forbiding it ? – Félix Gagnon-Grenier Sep 04 '14 at 14:35
  • 1
    @FélixGagnon-Grenier "The http-equiv attribute is an enumerated attribute" means it allows only values in the table in the spec. It even calls out caching in the later section ("other pragma directives"): > Pragma directives corresponding to headers that affect the HTTP processing model (e.g. caching) must not be registered, as they would result in HTTP-level behavior being different for user agents that implement HTML than for user agents that do not. – Kornel Sep 05 '14 at 14:44
  • Is the content restricted to only the 4 values defined above and what about `no-transform`, `max-age`, `s-maxage`, `must-revalidate`, `proxy-revalidate` ? Can we use these? – Ram Patra Dec 08 '14 at 12:33
  • 4
    The quoted document is not correct with respect to the `no-store` value (despite the document itself referencing [RFC 2068](http://www.w3.org/Protocols/rfc2068/rfc2068.txt)) - `no-store` prevents the document being stored/cached at all, anywhere. Whereas `no-cache` does allow it to be stored, but it must check with the server every time. Browsers will tend to store `no-cache` pages to [enable back button functionality](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching_FAQ) etc. – MrWhite Apr 01 '15 at 08:08
  • 3
    Google provides one of the easiest references for HTTP caching IMO: https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en#cache-control – MrWhite Apr 01 '15 at 08:08
142

You can set the headers in PHP by using:

<?php
  //set headers to NOT cache a page
  header("Cache-Control: no-cache, must-revalidate"); //HTTP 1.1
  header("Pragma: no-cache"); //HTTP 1.0
  header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past

  //or, if you DO want a file to cache, use:
  header("Cache-Control: max-age=2592000"); //30days (60sec * 60min * 24hours * 30days)

?>

Note that the exact headers used will depend on your needs (and if you need to support HTTP 1.0 and/or HTTP 1.1)

scunliffe
  • 57,883
  • 24
  • 118
  • 156
  • 4
    `Pragma` and `Expires` are probably redundant for the vast majority of browsers. https://www.fastly.com/blog/headers-we-dont-want – thijsai May 15 '18 at 22:04
  • 2
    @thijsai yeah HTTP/1.0 is massively out of date too... use only the headers you need based on your user matrix – scunliffe May 15 '18 at 22:32
  • For a better understanding of cache-control see https://csswizardry.com/2019/03/cache-control-for-civilians/ – Teenage Oct 16 '20 at 14:14
61

As I wrote is best to use the file .htaccess. However beware of the time you leave the contents in the cache.

Use:

<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=604800, public"
</FilesMatch>

Where: 604800 = 7 days

PS: This can be used to reset any header

brasofilo
  • 23,940
  • 15
  • 86
  • 168
William
  • 785
  • 5
  • 3
  • 3
    If you have access to your webserver configuration, you can put this there instead of in .htaccess. There is a misconception about that you have to put some things in .htaccess in Apache and it keeps getting fed by answers like these. You don't need ANY .htaccess unless you do not have direct acess to webserver config (e.g. in a multi vhost environment). Maybe just write webserver configuration OR .htaccess. See https://www.danielmorell.com/guides/htaccess-seo/basics/dont-use-htaccess-unless-you-must – Sybille Peters Jul 11 '20 at 15:37
  • Also you might add that you need mod_headers (or enclose it in an – Sybille Peters Jul 11 '20 at 15:37
31

The page at http://www.askapache.com/htaccess/apache-speed-cache-control.html suggests using something like this:

Add Cache-Control Headers

This goes in your root .htaccess file but if you have access to httpd.conf that is better.

This code uses the FilesMatch directive and the Header directive to add Cache-Control Headers to certain files.

# 480 weeks
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=290304000, public"
</FilesMatch>
Ivar
  • 4,655
  • 12
  • 45
  • 50
angry kiwi
  • 8,832
  • 21
  • 90
  • 132
  • 3
    Is order in this important? "max-age=290304000, public" Or "public, max-age=290304000" or both are equally right? – Satya Prakash Sep 08 '13 at 08:02
  • 2
    Order does not matter if the values are not conflicting (like `cache` and `no-cache`). `max-age` and `public` do not conflict so order does not matter. – Blaise Nov 25 '14 at 13:50
  • 2
    Note that since it uses the `Header` directive, you have to enable `mod_headers`. – Skippy le Grand Gourou Jan 25 '18 at 13:05
  • @Skippy le Grand Gourou how do I enable mod_headers? – Sam Jul 05 '18 at 06:56
  • @SamuelStratford I read it differs on other distributions, but under Debian you can either use `a2enmod` or make a symbolic link from `/etc/apache2/mods-available/headers.load` to `/etc/apache2/mods-enabled/headers.load`. – Skippy le Grand Gourou Jul 05 '18 at 14:19
26

This is the best .htaccess I have used in my actual website:

<ifModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file .(html?|txt|css|js|php|pl)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</ifModule>

##Tweaks##
Header set X-Frame-Options SAMEORIGIN

## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType text/css "access 1 month"
ExpiresByType text/html "access 1 month"
ExpiresByType application/pdf "access 1 month"
ExpiresByType text/x-javascript "access 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"
ExpiresByType image/x-icon "access 1 year"
ExpiresDefault "access 1 month"
</IfModule>
## EXPIRES CACHING ##

<IfModule mod_headers.c>
    Header set Connection keep-alive
    <filesmatch "\.(ico|flv|gif|swf|eot|woff|otf|ttf|svg)$">
        Header set Cache-Control "max-age=2592000, public"
    </filesmatch>
    <filesmatch "\.(jpg|jpeg|png)$">
        Header set Cache-Control "max-age=1209600, public"
    </filesmatch>
    # css and js should use private for proxy caching https://developers.google.com/speed/docs/best-practices/caching#LeverageProxyCaching
    <filesmatch "\.(css)$">
        Header set Cache-Control "max-age=31536000, private"
    </filesmatch>
    <filesmatch "\.(js)$">
        Header set Cache-Control "max-age=1209600, private"
    </filesmatch>
    <filesMatch "\.(x?html?|php)$">
        Header set Cache-Control "max-age=600, private, must-revalidate"
      </filesMatch>
</IfModule>
nicoX
  • 281
  • 5
  • 16
Erich García
  • 1,348
  • 18
  • 27
  • 3
    Almost perfect example of a .htaccess file... It would be complete if specific images were included & how to write the path to the image AND where to put the .htaccess file (eg. in image dir or index dir)?...eg. ' Header append Cache-Control "max-age=3600, must-revalidate" '... would this work?... OR... or pasted to img dir 'Header set Cache-Control "max-age=31536000, public"'... An _all the same_ strategy seems risky - anyway specific examples would be great if poss – Marco-UandL Nov 27 '16 at 20:31
  • 2
    just FYI: gzip compression on JS and CSS files can help to break your SSL encryption. If you rely on security, do not turn gzip on – Eduard Void May 17 '17 at 07:14
  • 1
    This is caching the login account page, so you can't log out from your account. Even worse someone can't just access the account page and be logged in with last users login. It's not advisable to use on an eCommerce site, you should then remove the `` to avoid static HTML pages to be cached. The rest of the filematches are ok. – nicoX May 25 '18 at 19:42
  • 1
    You have duplicated ``. – nicoX May 26 '18 at 13:10
  • 2
    You set `css` and `js` to private if you have proxy caching. I couldn't find any recommendations in your link regarding that. Most CDN's are recommending you cache those values. – nicoX May 28 '18 at 09:11
15

For Apache server, you should check mod_expires for setting Expires and Cache-Control headers.

Alternatively, you can use Header directive to add Cache-Control on your own:

Header set Cache-Control "max-age=290304000, public"
Gaurav Kansal
  • 239
  • 2
  • 15
Peter Štibraný
  • 31,128
  • 15
  • 85
  • 114
5

The meta cache control tag allows Web publishers to define how pages should be handled by caches. They include directives to declare what should be cacheable, what may be stored by caches, modifications of the expiration mechanism, and revalidation and reload controls.

The allowed values are:

Public - may be cached in public shared caches
Private - may only be cached in private cache
no-Cache - may not be cached
no-Store - may be cached but not archived

Please be careful about case sensitivity. Add the following meta tag in the source of your webpage. The difference in spelling at the end of the tag is either you use " /> = xml or "> = html.

    <meta http-equiv="Cache-control" content="public">
    <meta http-equiv="Cache-control" content="private">
    <meta http-equiv="Cache-control" content="no-cache">
    <meta http-equiv="Cache-control" content="no-store">

Source-> MetaTags

Karthik N G
  • 1,755
  • 1
  • 16
  • 18
  • correction: no-store should not be cached, no cache is allowed to be cached but must be checked with the server before being reserved - see http://palizine.plynt.com/issues/2008Jul/cache-control-attributes/ – DangerMouse Jan 02 '13 at 11:14
  • Cache-Control no-store - no-store is similar to no-cache in that the response cannot be cached and re-used, however there is one important difference. no-store requires the resource to be requested and downloaded from the origin server each time. This is an important feature when dealing with private information. – MarcoZen Feb 12 '20 at 00:39
5

OWASP recommends the following,

Whenever possible ensure the cache-control HTTP header is set with no-cache, no-store, must-revalidate, private; and that the pragma HTTP header is set with no-cache.

<IfModule mod_headers.c>
    Header set Cache-Control "private, no-cache, no-store, proxy-revalidate, no-transform"
    Header set Pragma "no-cache"
</IfModule>
Won Jun Bae
  • 4,379
  • 5
  • 39
  • 48
  • Can you add a link? Also, doesn't this depend on the type of content? Why always set no-store? Why private? Only makes sense for pages that are private. – Sybille Peters Jul 11 '20 at 15:41