Cache Busting... Anyone have any tricks

This probably isn’t the best site to ask, but I figure there may be some devs out there who’ve struggled with this as well. Basically my question is…

What method do you use to force a client’s browser to download an updated page, such that the client doesn’t have to “refresh” or "clear their cache?

This is known in common parlance as “cache busting.” I’ve read about a bunch of different ways, but nobody seems to agree on what is the BEST way.

Any thoughts Pinegrowers?

1 Like

Don’t know what the best method is, and what kind of solutions you already found. I would say use the “Cache-Control” Header.

Use some combination with max-age, no-cache and must-revalidate. You can place them in your head / meta tags, or a htaccess file.

Marf,

Thanks. That’s actually what I settled on. I did it with PHP.

What is the easiest way of implementing this? I think that most websites I make require this. Can anyone give me an example please? I know that
Cache-Control: no-cache, no-store, must-revalidate
has to be added but where? Thanks.


HTACCESS

<IfModule mod_headers.c>
  Header set Cache-Control "no-cache, no-store, must-revalidate"
  Header set Pragma "no-cache"
  Header set Expires 0
</IfModule>

Better use it with “file match” for html, htm and php files only.

<IfModule mod_headers.c>
<FilesMatch "\.(html|htm|php)$">
  Header set Cache-Control "no-cache, no-store, must-revalidate"
  Header set Pragma "no-cache"
  Header set Expires 0
</filesMatch>
</IfModule>

PHP

header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');

Important: set this headers before any content (html or whitespace) is send to the browser!


HTML (head tag)

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">

edit:
If you are going to use this, do also some background research about “cache control”, to know what you are doing. Instead of just copy/paste a piece of code.

2 Likes

Thank you for the code examples.
So if I was to place the three lines of HTML code above into the head of my pages it would work?
That’s really great!

Here are some strategies for cache busting CSS files, e.g. query strings at the end of the file name or changing the file name.
(Please note that this is only recommended for some selected files, such as a main CSS file. )

Edit: On googles new web.dev website, you can also find a general overview about the options in your caching toolbox.

I have tried the HTML Meta method and it has not always worked with all browsers. Chrome seems to be exceptionally aggressive in its caching.

@Jim Using one method is enough, htaccess, PHP or HTML.
When you use more methods (at a time), they are processed/overruled in that order.

By using the HTML method, you have to add it to every single HTML file (can be a lot of work). Using htaccess, you can configure it for the whole site (or directory) with just one htaccess file.


DO I NEED IT ?
I would like to mention that “disabling caching” looks very attractive and a perfect solution, but it’s not always a good idea, I would only use it when there is a very good reason!

Because when disabled it means more (maybe unnecessary) requests, data traffic and load to the server. On a slow/crowded or very high traffic server, it’s not always desirable.

And with a slower (mobile) connection, it takes longer to constantly load everything again from the server, which is not good for a positive user experience. And for connections with a dataplan (mobile), it cost more data for the user(s) from their dataplan.


MAX-AGE and FILESMATCH

When your pages/content is not constantly changing. It’s not really necessary to disable caching. Better leave it as it is, or maybe use and configure a “Max-Age” or a “Expiration” value. For lets say: 15 min, 1 hour, 1 day or a week.

And with htaccess and “FilesMatch” you can control it easily by filetype, and use different control settings.

htaccess file (example)

<IfModule mod_headers.c>

# no caching
<FilesMatch "\.(html|htm|php)$">
  Header set Cache-Control "no-cache, no-store, must-revalidate, private"
  Header set Pragma "no-cache"
  Header set Expires 0
</filesMatch>

# 1 day - max-age
<FilesMatch "\.(txt|xml|js|css)$">
  Header set Cache-Control "max-age=86100, public"
</FilesMatch>

# 1 week - max-age
<FilesMatch "\.(jpg|jpeg|png|gif)$">
  Header set Cache-Control "max-age=604800, public"
</FilesMatch>

</IfModule>
  • max-age : Values are set in seconds.
  • public : Indicates that the response may be cached by any cache.
  • private : Indicates that the response is intended for a single user and must not be stored by a shared cache. A private cache may store the response.

DEVELOPMENT STAGE
While you are still in developing stage, and constantly making changes. Caching can be very annoying!
You can decide to temporarily disable it (with htaccess) during the development process.

When the site/project is done and ready to publish, you can easily remove the caching limitations for the production server (remove/change that htaccess file).


1 Like

Hello, I am very happy with all of the information. It seems the .htaccess solution would be the best way forward. Does it matter where in my .htaccess file I put the necessary code? It will be nice to get my websites all updating again! Thank you.

Hmmm, annoying and strange that Chrome is acting that way. Is Chrome always “aggressive with caching”, no matter which method you use? You said earlier that you tried also with PHP, did that worked better or different…??


If you have “rewrite rules” in your htaccess file, You need to place it below them. Don’t know if htaccess is the best method, but I prefer htaccess. Also because it’s better to maintain and control.

Edit
The code I posted was just intended as an example, for explaining it! You have to find out, and decide for yourself, how to use it for your own personal situation. Maybe you need to change some things or add some things.


Woah man, this is some good info! Cheers for the Info guys.
I wasn’t aware of some/most of this! excellent.

I might well fire this up on my Local host for private webdev - and, Im quite suprised Ive never seen such a collection of info before, I’ve looked.

It was good that there was a link for CSS cache busting too.
All very interesting. I’ve lots on at the mo, but this needs exploring.
Great. Thanks
:slight_smile:
(ps, @Marf… I’ve also been sidetracked by PineHoundPartyHats :wink: )

2 Likes

Off-topic:

Is the domain : “PineHoundPartyHats[.]com” still available…
Maybe a new business opportunity, to start an online shop!
:star_struck: :crazy_face: :money_mouth_face:


Woof! Woof!

…pssssst… Silently pees on PineSaplings…

Damn you, PinePuppies!

…hee hee and yeah that phrase kind of rolled off my tongue…which makes a nice change from what usually does …okaaay then, and, back on topic!

Very good information to have on hand. Thank you all for sharing!

mmm would this help?

https://selfcontrolapp.com

I am trying to improve my focus and this blocks apps connecting to the internet for a time period and … clears browser caches to stop you reading them instead :slight_smile:
Clever.

But not sure as the lowest time is 0 and 15 minutes. that might be infuriating.
oh and its Mac only.

also for Mac is Onyx app (free system utility, amazing if you have never used it, that can do it too)

If you want more granular control e.g. you just updated a CSS file, and you use a CMS or PHP then setup $cachebuster as a global variable in a config file…e.g.

<?php
// config.php

define("CACHEBUSTER", "randomstring4567";

?>

then in your html/php file

<link rel="stylesheet" type="text/css" href="css/style.css?v=<?php echo CACHEBUSTER ?>">

Do this for files you change often when you still in the middle of designing. Then just increment the variable when you’re ready to have the client pull the updated file.

Something I found that works every time (at least for me) is simple:

example.jpg?nocache=<?php echo time(); ?>
style.css?nocache=<?php echo time(); ?>
javascript.js?nocache=<?php echo time(); ?>

May not be the best (or efficient), but sure works good for me:)

Yes, that’s what I was going to suggest. I recommend using Webpack, when it comes to bundling your CSS+JS for production with which is easy to work. But there are other options like Gulp with tons of examples on GitHub and the Internet in general.

For instance, in my webpack.config.js, I have all files to output something like this: filename: '[name]-[hash:7].bundle.js'

So, all CSS, JS, images, etc. have their name and then the first seven characters of their hash. Like styles-34F8EE.css

Since Webpack takes care of injecting the dependencies in your HTML’s you can forget about it. For a more mundane and easier approach, something like what @oleteacher mentioned example.jpg?nocache=<?php echo time(); ?> is effortless and works.

I remember using Gulp with a couple of lines of code to process all my files (every time I roll out an update) like this interpolation: photo.png?v=${new Date().getTime()} which right now computes to photo.png?v=1564845376610 (the number of milliseconds since the 1st of Jan 1970, so it’s always unique)

I think Pinegrow should put a current Timestamp at the end of the css file name when you save changes. This would be the easiest way. I could be an optional behavior which can be activated in the settings.