app/controllers/offline-controller.js

/**
 * @module offline-resources-controller
 */

const fs = require( 'fs' );
const path = require( 'path' );
const crypto = require( 'crypto' );
const express = require( 'express' );
const router = express.Router();
const config = require( '../models/config-model' ).server;

// var debug = require( 'debug' )( 'offline-controller' );

module.exports = app => {
    app.use( `${app.get( 'base path' )}/`, router );
};
router
    .get( '/x/offline-app-worker.js', ( req, res, next ) => {
        if ( config[ 'offline enabled' ] === false ) {
            var error = new Error( 'Offline functionality has not been enabled for this application.' );
            error.status = 404;
            next( error );
        } else {
            res
                .set( 'Content-Type', 'text/javascript' )
                .send( getScriptContent() );
        }
    } );

/**
 * Assembles script contentå
 */
function getScriptContent() {
    // Determining hash every time, is done to make development less painful (refreshing service worker)
    // The partialScriptHash is not actually required but useful to see which offline-app-worker-partial.js is used during troubleshooting.
    // by going to http://localhost:8005/x/offline-app-worker.js and comparing the version with the version shown in the side slider of the webform.
    const partialOfflineAppWorkerScript = fs.readFileSync( path.resolve( config.root, 'public/js/src/module/offline-app-worker-partial.js' ), 'utf8' );
    const partialScriptHash = crypto.createHash( 'md5' ).update( partialOfflineAppWorkerScript ).digest( 'hex' ).substring( 0, 7 );
    const configurationHash = crypto.createHash( 'md5' ).update( JSON.stringify( config ) ).digest( 'hex' ).substring( 0, 7 );
    const version = [ config.version, configurationHash, partialScriptHash ].join( '-' );
    // We add as few explicit resources as possible because the offline-app-worker can do this dynamically and that is preferred
    // for easier maintenance of the offline launch feature.
    const resources = config[ 'themes supported' ]
        .reduce( ( accumulator, theme ) => {
            accumulator.push( `${config['base path']}${config['offline path']}/css/theme-${theme}.css` );
            accumulator.push( `${config['base path']}${config['offline path']}/css/theme-${theme}.print.css` );

            return accumulator;
        }, [] )
        .concat( [
            `${config['base path']}${config['offline path']}/images/icon_180x180.png`
        ] );

    return `
const version = '${version}';
const resources = [
    '${resources.join( '\',\n    \'' )}'
];

${partialOfflineAppWorkerScript}`;

}