Skip to content

Instantly share code, notes, and snippets.

@velizarn
Created September 10, 2018 07:16
Show Gist options
  • Save velizarn/c1fcecf6d0658d6f9ba32e6b63a12c74 to your computer and use it in GitHub Desktop.
Save velizarn/c1fcecf6d0658d6f9ba32e6b63a12c74 to your computer and use it in GitHub Desktop.
Generate service worker file
importScripts('/js/workbox-sw.js');
workbox.setConfig({
debug : true
});
workbox.core.setLogLevel(workbox.core.LOG_LEVELS.debug);
workbox.skipWaiting();
workbox.clientsClaim();
workbox.core.setCacheNameDetails({
"prefix" : "nodepwa",
"suffix" : "web",
"precache" : "install-time",
"runtime" : "run-time"
});
const fileManifest = [
{
"url" : "/css/app.css",
"revision" : "c5be93286dfb80f7b59a4a58191ab6c8"
}, {
"url" : "/js/vendor/jquery-3.2.1.slim.min.js",
"revision" : "d7a8202ab8c3362b7945b133f5ac5d6a"
}
];
workbox.precaching.precacheAndRoute(fileManifest);
const crypto = require('crypto'), fs = require('fs')
const fileHash = (filename, url = '', algorithm = 'md5') => {
return new Promise((resolve, reject) => {
// Algorithm depends on availability of OpenSSL on platform
// Another algorithms: 'sha1', 'md5', 'sha256', 'sha512' ...
let shasum = crypto.createHash(algorithm);
try {
let s = fs.ReadStream(filename)
s.on('data', (data) => {
shasum.update(data)
})
s.on('end', () => {
const hash = shasum.digest('hex')
return resolve({ url, revision: hash });
})
} catch (error) {
return reject('calc fail');
}
});
}
const swConfig = (strings, ...values) => {
const _fileManifest = values[0] || [];
const _wboxPath = values[1] || '/js/workbox-sw.js';
const debugMode = values[2] || false;
const cacheNames = values[3] || {};
return (`importScripts('${_wboxPath}');
workbox.setConfig({ debug: ${debugMode} });
workbox.core.setLogLevel(workbox.core.LOG_LEVELS.debug);
workbox.skipWaiting();
workbox.clientsClaim();
workbox.core.setCacheNameDetails(${cacheNames});
const fileManifest = ${_fileManifest};
workbox.precaching.precacheAndRoute(fileManifest);`).replace(/ /gm, '');
};
const displayServiceWorker = (strings, ...values) => {
const pathToSW = values[0] || '/sw.js';
return (`<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('${pathToSW}').then(function(registration) {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
console.log('ServiceWorker registration failed: ', err);
});
});
}
</script>
`)
};
const config = require(__dirname + '/sw-config.js');
const tasks = config.fileManifest.map((item) => {
return fileHash(item.path, item.url)
});
tasks.reduce((promiseChain, currentTask) => {
return promiseChain.then(chainResults =>
currentTask.then(currentResult =>
[ ...chainResults, currentResult ]
)
);
}, Promise.resolve([])).then(arrayOfResults => {
const manifestData = JSON.stringify(arrayOfResults);
const serviceWorkerContent = swConfig`File manifest data: ${manifestData}; path to workbox file ${config.pathToWorkbox}; debug mode: ${true}; cache names: ${JSON.stringify(config.cacheNames)}`;
fs.writeFileSync(config.swOutputFile, serviceWorkerContent);
console.log('Add following script to your HTML:\n---');
console.log(displayServiceWorker`Path to sw.js ${'/sw.js'}`)
});
// https://decembersoft.com/posts/promises-in-serial-with-array-reduce/
// https://stackoverflow.com/questions/20100245/how-can-i-execute-array-of-promises-in-sequential-order
module.exports = {
fileManifest: [
{
path: __dirname + '/public/css/app.css',
url: '/css/app.css'
},
{
path: __dirname + '/public/js/vendor/jquery-3.2.1.slim.min.js',
url: '/js/vendor/jquery-3.2.1.slim.min.js'
}
],
debugMode: true,
logLevel: 'debug',
pathToWorkbox: '/js/workbox-sw.js',
swOutputFile: __dirname + '/public/sw.js',
cacheNames: {
prefix: 'nodepwa',
suffix: 'web',
precache: 'install-time',
runtime: 'run-time'
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment