Motivated by the sudden appearance of the "Add to home screen" prompt, I spent the last couple of hours to tune my Service Worker / caching behaviour:
- I can now exclude parts of my site from the service worker. This was an important feature for me, since the WordPress backend didn't sit too well with stubborn cached items.
- I established a number of caches for different items:
-- a "static" cache that has the base css and the page that gets displayed when the network is offline.
-- a "content" cache, that stores up to 25 URLs a visitor has, well, visited, while being online.
-- an "image" cache, that stores up to 45 image files, and finally
-- an "asset" cache for up to 35 files (everything that is not HTML and not an image).
The limits are rather random, but I think each cache has an build-in maximum of 50 entries (?), so to see if it works, I choosed numbers smaller than that.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | 'use strict'; (function() { // Update 'version' if you need to refresh the cache const version = '0.1.1'; const staticCache = 'wbr_static'; const contentCache = 'wbr_content'; const imgCache = 'wbr_images'; const assetCache = 'wbr_assets'; const staticCacheName = version + '_' + staticCache; const contentCacheName = version + '_' + contentCache; const imgCacheName = version + '_' + imgCache; const assetCacheName = version + '_' + assetCache; // urls that should not be controlled/cached const neverCache = [ 'piwik', '/jaguar/', '/blog/wp-admin/' ]; // helper for checking the neverCache array var testPos = function(cur,idx,arr){ // 'this' will be triggered by the 'thisVar' param in array.some(callback,thisVar), // i.e. neverCache.some(testPos,request.url) if( this.indexOf(cur) !== -1 ){ return true; } return false; } // Store core files in a cache (including a page to display when offline) var updateStaticCache = function() { return caches.open( staticCacheName ) .then(function (cache) { return cache.addAll([ '/blog/wp-content/themes/wbr-theme/style.css', '/blog/wp-content/uploads/2016/04/image-6-530x398.png', '/', '/offline.html' ]); }); }; // Put an item in a specified cache var stashInCache = function(cacheName, request, response) { caches.open(cacheName) .then(function (cache) { cache.put(request, response); }); }; // Limit the number of items in a specified cache. var trimCache = function(cacheName, maxItems) { caches.open(cacheName) .then(function (cache) { cache.keys() .then(function (keys) { if (keys.length > maxItems) { cache.delete(keys[0]) .then(trimCache(cacheName, maxItems)); } }); }); }; // Remove caches whose name is no longer valid var clearOldCaches = function() { return caches.keys() .then(function (keys) { return Promise.all(keys .filter(function (key) { return key.indexOf(version) !== 0; }) .map(function (key) { return caches.delete(key); }) ); }) } self.addEventListener('install', function (event) { event.waitUntil(updateStaticCache() .then(function () { return self.skipWaiting(); }) ); }); self.addEventListener('activate', function (event) { event.waitUntil(clearOldCaches() .then(function () { return self.clients.claim(); }) ); }); self.addEventListener('message', function(event) { if (event.data.command == 'trimCaches') { trimCache(contentCacheName, 25); trimCache(imgCacheName, 45); trimCache(assetCacheName, 35); } }); self.addEventListener('activate', function (event) { event.waitUntil( caches.keys() .then(function (keys) { // Remove caches whose name is no longer valid return Promise.all(keys .filter(function (key) { //console.log(key); //console.log(key.indexOf(version) !== 0); return key.indexOf(version) !== 0; }) .map(function (key) { return caches.delete(key); }) ); }) ); }); self.addEventListener('fetch', function (event) { var request = event.request; // if is request for cms admin, do nothing. if( neverCache.some(testPos,request.url)){ return } // Always fetch non-GET requests from the network if (request.method !== 'GET') { event.respondWith( fetch(request) .catch(function () { return caches.match('/offline.html'); }) ); return; } // For HTML requests, try the network first, fall back to the cache, finally the offline page if (request.headers.get('Accept').indexOf('text/html') !== -1) { // Fix for Chrome bug: https://code.google.com/p/chromium/issues/detail?id=573937 if (request.mode != 'navigate') { request = new Request(request.url, { method: 'GET', headers: request.headers, mode: request.mode, credentials: request.credentials, redirect: request.redirect }); } event.respondWith( fetch(request) .then(function (response) { // Stash a copy of this page in the cache var copy = response.clone(); stashInCache(contentCacheName, request, copy); return response; }) .catch(function () { return caches.match(request) .then(function (response) { return response || caches.match('/offline.html'); }) }) ); return; } // For non-HTML requests, // - look in the cache first, // - fall back to the network, cache it, // - else show offline img if is image request event.respondWith( caches.match(request) .then(function (response) { return response || fetch(request) // update asset | image cache .then(function (response) { // Stash a copy of this page in the cache. var copy = response.clone(); var myCache = assetCacheName; if (request.headers.get('Accept').indexOf('image') !== -1) { myCache = imgCacheName; } stashInCache(myCache, request, copy); return response; }) .catch(function () { // If the request is for an image, show an offline placeholder if (request.headers.get('Accept').indexOf('image') !== -1) { return new Response('Offlineoffline', { headers: { 'Content-Type': 'image/svg+xml' }}); } }); }) ); }); })(); |
I'm quite pleased with myself because the script still works after all these changes, and I think I'm beginning to grasp how this hot new stuff is supposed to work :-)
Thanks Jeremy @adactio for the "blogServiceworker" gist, and Steffen @webgefrickel for the idea for the "neverCache" array.
3 Reaktionen zu “Revisiting the Service Worker / Offline cache”
Kommentare sind geschlossen.