1const cacheName = 'dokuwiki PWA cache'; 2 3self.addEventListener('install', function (e) { 4 idbKeyval.del('lastSync'); 5}); 6 7self.addEventListener('message', function (e) { 8 9 // console.log("[ServiceWorker] Received Message:"); 10 // console.log(e.data.type); 11 12 switch (e.data.type) { 13 case 'updatePages': 14 cachePages(e, e.data.pages); 15 break; 16 case 'getLastUpdate': 17 idbKeyval.get('lastSync').then((value) => e.source.postMessage( 18 { 19 type: 'lastUpdate', 20 ts: value, 21 } 22 )); 23 break; 24 case 'getHashVersion': 25 e.source.postMessage( 26 { 27 type: 'swHashVersion', 28 hash: swHashVersion, // injected when serviceworker is constructed in PHP 29 } 30 ) 31 } 32 33}); 34 35function cachePages(e, data) { 36 idbKeyval.set('lastSync', Math.floor(Date.now()/1000)); 37 e.waitUntil( 38 caches.open(cacheName).then(function (cache) { 39 40 // if (r) { 41 // const lmTimeString = r.headers.get('Last-Modified'); 42 // const ts = (new Date( lmTimeString )).getTime(); 43 // console.log('we have a cache for ' + e.request.url + ' from ', lmTimeString, ts); 44 // } 45 return Promise.all(data.map(function (pageData) { 46 return cache.add(pageData.link) 47 })); 48 }) 49 ); 50} 51 52self.addEventListener('activate', function (e) { 53 console.log('[ServiceWorker] Activate'); 54}); 55 56const CACHED_DESTINATIONS = [ 57 'document', 58 'style', 59 'script', 60 'image', 61 'font', 62]; 63 64const OFFLINE_FIRST_DESTINATIONS = [ 65 'script', 66 'style', 67 'font', 68]; 69 70self.addEventListener('fetch', function (e) { 71 if (e.request.method !== 'GET') { 72 return; 73 } 74 75 if (!CACHED_DESTINATIONS.includes(e.request.destination)) { 76 // only cache important modes 77 return; 78 } 79 80 if (OFFLINE_FIRST_DESTINATIONS.includes(e.request.destination)) { 81 e.respondWith(cacheFirst(e.request)); 82 return; 83 } 84 85 e.respondWith(networkFirst(e.request)); 86}); 87 88function networkFirst(request) { 89 return fromNetwork(request, 400).then(function (response) { 90 if (response.headers.has('X-DWPLUGIN-PWAOFFLINE-ACT') && 91 response.headers.get('X-DWPLUGIN-PWAOFFLINE-ACT') !== 'show') { 92 // don't cache modes other than show 93 return response; 94 } 95 return caches.open(cacheName).then(function (cache) { 96 cache.put(request, response.clone()); 97 return response; 98 }); 99 }).catch(function () { 100 return fromCache(request); 101 }) 102} 103 104function cacheFirst(request) { 105 return caches.match(request).then(function (cacheResponse) { 106 return cacheResponse || fetch(request).then(function (response) { 107 return caches.open(cacheName).then(function (cache) { 108 cache.put(request, response.clone()); 109 return response; 110 }); 111 }); 112 }) 113} 114 115function fromNetwork(request, timeout) { 116 return new Promise(function (fulfill, reject) { 117 const timeoutId = setTimeout(reject, timeout); 118 fetch(request).then(function (response) { 119 120 if (response.status >= 500) { 121 reject(); 122 } 123 clearTimeout(timeoutId); 124 fulfill(response); 125 }, reject); 126 }); 127} 128 129function fromCache(request) { 130 if (!CACHED_DESTINATIONS.includes(request.destination)) { 131 return Promise.reject('no-match'); 132 } 133 134 return caches.open(cacheName).then(function (cache) { 135 return cache.match(request).then(function (matching) { 136 if (matching) { 137 return matching; 138 } 139 if (request.destination === 'document') { 140 return new Response('Page not available. Please go back.', { 141 headers: { 142 'Content-Type': 'text/plain' 143 } 144 }); 145 } 146 return Promise.reject('no-match'); 147 }); 148 }); 149} 150