What is Cache Busting? And How I Implement It with Perch.

by Will Moody

What is Cache Busting? And How I Implement It with Perch.

Cache busting is useful because it allows your visitors to receive the most recently updated files without having to perform a hard refresh or clear their browser cache, which many are unlikely to do. From a developer’s point of view, using cache busting is beneficial so that the latest changes can be pushed out and become available to everyone immediately.

There are a few methods you can use to take advantage of cache busting:

  • File name versioning (e.g. style.v2.css)
  • File path versioning (e.g. /v2/style.css)
  • Query strings (e.g. style.css?ver=2)

Both file name versioning and file path versioning are recommended cache busting methods. They do not interfere with any caching mechanisms and can be easily updated to reflect a modified file.

The one common approach used is to add a query string with the version or with the file modification time to the URL of the asset in question, as below:-

<link rel="stylesheet" href="../../assets/css/app_min.css</a>?ver=2">


The problem with this approach is that depending on what servers the visitor’s connection is passing through, the assets will not be cached at all. The query string appended to the end of the URL makes some proxy servers assume that the content of that file is dynamic in nature, and dependent on the current value of the query string.

This is also the reason why some page speed analysis tools will flag your assets if they contain such a query string.

How to get over this?

The better solutions are to use either file name versioning or file path versioning. My preferred method is file name versioning.

My Approach

As I use Gulp for my workflow, so my static assets are run through a gulp pipeline, there are a few steps added to the process. I personally like to keep all my scss/sass in separate partials files, each relating to a section say header, nav or footer and then things like the grid, typography and forms are all kept separate, this makes finding a particular piece of scss/sass much easier to find, so for me using Sass partials for concatenating works perfectly. Once prefixed and concatenated, I add .min to the end of the file name with npm rename.

This is the relevant section from my Gulpfile


// Compile sass into CSS & auto-inject into browsers
gulp.task('sass', function() {
  return gulp.src("src/scss/*.scss")
    .pipe(sourcemaps.init())
    .pipe(plumber())
    .pipe(sass())
    .pipe(autoprefixer({
      browsers: ['last 2 versions'],
      cascade: false
    }))
    .pipe(cssnano())
    .pipe(gulp.dest("assets/css"))
    .pipe(rename('apps.min.css'))
    .pipe(sourcemaps.write('../maps'))
    .pipe(gulp.dest("assets/css"))
    .pipe(browserSync.stream());
});

The next part of the build process is within your page head is to add the following, which comes from this excellent article by Jay George:-

<!--?php $CSSversion = filemtime($_SERVER['DOCUMENT_ROOT'].'/assets/css/apps.min.css'); ?-->
<link rel="stylesheet" href="/assets/css/apps.min.<?php echo $CSSversion ?>.css" type="text/css" media="screen">
<!--?php $CSSversion = filemtime($_SERVER['DOCUMENT_ROOT'].'/assets/css/print.min.css'); ?-->
<link rel="stylesheet" href="/assets/css/print.min.<?php echo $CSSversion ?>.css" type="text/css" media="print">

This code adds a timestamp to the file in this case apps.min.css and also to my print.min.css file,  so changing it from apps.min.css to something like apps.min.12345678.css  and form print.min.css to print.min.12345678.css.

The same approach can be used for your js files but this time using :-

<!--?php $JSversion = filemtime($_SERVER['DOCUMENT_ROOT'].'/assets/js/scripts.min.js'); ?-->
<script src="/assets/js/scripts.min.<?php echo $JSversion ?>.js" defer="defer"></script>

Rewrite Rules in .htaccess

The issue with adding a timestamp to your file is that we don't actually have a file called apps.min.12345678.css so we need to use  a rewrite rule in our .htaccess to overcome this.

In my case it's as simple as this :-

# Cache Breaking
RewriteRule (assets/)([^.]*).min.+.(css|js)$ $1$2.min.$3

but when using Perch Runway I found I needed to add in public_html as I build in a public_html branch :-

# Cache Breaking
# ---------------
RewriteRule (public_html/assets/)([^.]*).min.+.(css|js)$ $1$2.min.$3

Please note that these rules have to come before some of your other rewrite rules when using Perch Runway.

I hope this is has been helpful and once again thanks to Jay George for his excellent article.