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", } } }