Ionic App Bundled Files Cache Busting

Ionic App Bundled Files Cache Busting

When building Progressive Web Apps (PWA), there is actually another technology used allowing you to use a web app while offline, send push notifications, and scheduled background sync. Service workers provide all those functionalities that the said features rely on.

A service worker is a script that your browser runs in the background, separate from a web page, allowing site features to run even without user interaction.

An Ionic web app uses a service worker-toolbox, a utility library (like lodash/jquery) for working with the service worker API. This is already included by default in a new Ionic app, so there’s no extra setup required.

Service workers cache resources such as Javascript, CSS, and images from the time it is registered. Cached resources are only updated when any of the cached files are changed.

While that sounds overwhelming, it also comes with a disadvantage when you are still in the development stage. When you implement a few changes in your app and deployed it in production, you might notice that the changes you made don’t take effect. That’s because you might still be using the cached resources in your browser.

So when using an ionic app, cache busting is essential to make sure your users are always running the latest version. The best way to do this is by appending a hash to filenames in the build phase. This will make sure that any changed files will be instantly re-fetched by the browser, but it can safely cache everything that hasn’t changed.

The Angular CLI already supports it in the build process but not in Ionic.

Create a cache-busting.js file that you can add to run in your post-build process and add the following codes.

#!/usr/bin/env node

var fs = require('fs'),
        path = require('path'),
        cheerio = require('cheerio'),
        revHash = require('rev-hash');

/**
 *
 * @param string fileName
 * @returns string
 */
function hashFile(file) {

    // Get file name
    var fileName = file.replace(/\.[^/.]+$/, "");
    // Get file extension
    var re = /(?:\.([^.]+))?$/;
    var fileExtension = re.exec(file)[1];

    var filePath = path.join(buildDir, file);
    var fileHash = revHash(fs.readFileSync(filePath));
    var fileNewName = `${fileName}.${fileHash}.${fileExtension}`;
    var fileNewPath = path.join(buildDir, fileNewName);
    var fileNewRelativePath = path.join('build', fileNewName);

    //Rename file
    console.log(`${fileName}.${fileExtension} >> ${fileName}.${fileHash}.${fileExtension}`);
    fs.renameSync(filePath, fileNewPath);

    return fileNewRelativePath;
}


var rootDir = path.resolve(__dirname, '././');
var wwwRootDir = path.resolve(rootDir, 'www');
var buildDir = path.join(wwwRootDir, 'build');
var indexPath = path.join(wwwRootDir, 'index.html');
$ = cheerio.load(fs.readFileSync(indexPath, 'utf-8'));

$('head link[href="build/main.css"]').attr('href', hashFile('main.css'));
$('body script[src="build/main.js"]').attr('src', hashFile('main.js'));
$('body script[src="build/polyfills.js"]').attr('src', hashFile('polyfills.js'));
$('body script[src="build/vendor.js"]').attr('src', hashFile('vendor.js'));

fs.writeFileSync(indexPath, $.html());

Run the following command in your terminal to give npm permission to run the cache busting script

chmod 755 ./cache-busting.js

And in your package.json, add the postbuild script to handle the cache-busting process.

{
  "author": "OmelSoft Solution",
  "homepage": "https://www.omelsoft.com/",
  "scripts": {
        "start": "ionic-app-scripts serve",
        "build": "ionic-app-scripts build",
        "postbuild": "node ./cache-busting.js",
    }
  }
}

Cromwell Bayon

He is a self-tutored programmer and a Full-Stack Developer. He strives to excel in the newest technology as possible. He has a very high sense of technicality and analytical skills which allows him to resolve any kind of issues related to technology. He also loves woodworking. Read more about him here...

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.