OmelSoft

Ionic App Bundled Files Cache Busting

When building Progressive Web Apps (PWA), there are actually other technology used allowing you to use a web app while offline, send push notifications and scheduled background sync. Service workers provides all those functionality 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 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 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 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 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",
    }
  }
}

Add comment

E-mail is already registered on the site. Please use the Login form or enter another.

You entered an incorrect username or password

Sorry, you must be logged in to post a comment.