Cache Busting Css and Js files

by Will Moody


Cache busting solves the browser caching issue by using a unique file version identifier to tell the browser that a new version of the file is available. Therefore the browser doesn’t retrieve the old file from cache but rather makes a request to the origin server for the new file.

To implement cache-busting with the static website boilerplate the method I use is relatively simple, it involves a handlebars helper which on file builds timestamps the name of the css and js calls in the head and footer of each page.

The handlebars helper is as follows and is included in the gulpfile.js with the boilerplate, it's the first helper in the list and creates a time/date stamp:-

extract of gulpfile.js

// templates
gulp.task('templates', (done) => {
  assemble({
    layouts: config.templates.layouts,files 
    views: config.templates.src,
    materials: config.templates.partials,
    data: config.templates.data,
    keys: {
      views: 'templates',
      materials: 'components',
    },
    dest: config.templates.dest,
    logErrors: config.dev,
    helpers: {
      // head <link rel="stylesheet" href="{{baseurl}}/assets/styles/main.css?v={{release}}">
      release: function release() {
        return new Date().getTime();
      },

This time/date stamp is then included in the css/js calls as follows:-

extract of head

  <!-- css -->
  <link rel="stylesheet" href="{{baseurl}}/assets/styles/main.css?v={{release}}" media="screen">
  <link rel="stylesheet" href="{{baseurl}}/assets/styles/print.css?v={{release}}" media="print">

  <script src="{{baseurl}}/assets/scripts/main.js?v={{release}}" async="" defer=""></script>

This results in a unique css/js call everytime any changes are made:-

extract of head

  <link rel="stylesheet" href="/assets/styles/main.css?v=1535057792788" media="screen">
  <link rel="stylesheet" href="/assets/styles/print.css?v=1535057792788" media="print">

  <script src="/assets/scripts/main.js?v=1535057792788" async="" defer=""></script>

This at the moment adds a query string timestamp, which is not ideal as there can be issues with certain proxies and cdn's ignoring the query string, in time I will look for an alternative and then amend this post.