I want to add service worker to my site to offer a good offline experience to my site users. (Site back-end is PHP)
I'm still new to Javascript promises and service workers, but here is what i reached so far :
my index.php page has this script to register service worker
<script>
if ('serviceWorker' in navigator) { navigator.serviceWorker.register('sw.js')};
</script>
and for service worker file i use the following code
var CACHE_STATIC_NAME = 'static-v74';
var CACHE_DYNAMIC_NAME = 'dynamic-v74';
self.addEventListener('install', function (event) {
console.log('Installing Service Worker ...', event);
event.waitUntil(
caches.open(CACHE_STATIC_NAME)
.then(function (cache) {
console.log('Precaching App Shell');
cache.addAll([
'offline.php', // offline page
'assets/bundle.css',
'assets/bundle.js',
'assets/images/logo.jpg',
'assets/images/favicon.ico'
]);
})
)
});
self.addEventListener('activate', function (event) {
console.log('Activating Service Worker ....', event);
event.waitUntil(
caches.keys()
.then(function (keyList) {
return Promise.all(keyList.map(function (key) {
if (key !== CACHE_STATIC_NAME && key !== CACHE_DYNAMIC_NAME) {
console.log('Removing old cache.', key);
return caches.delete(key);
}
}));
})
);
return self.clients.claim();
});
self.addEventListener('fetch', function(event) {
event.respondWith(
// Try the network
fetch(event.request)
.then(function(res) {
return caches.open(CACHE_DYNAMIC_NAME)
.then(function(cache) {
// Put in cache if succeeds
cache.put(event.request.url, res.clone());
return res;
})
})
.catch(function(err) {
// Fallback to cache
return caches.match(event.request);
})
);
});
in fact this code is working fine as expected :
(1) It registers the service worker & take copy of my static cache files. (2) When activating a new service worker it removes the old cache. (3) With every new request it fetches from network first & if succeeded it puts a fresh copy of request in cache. (4) If failed to make network request when offline it gives back the user a fresh copy of last network request.
what i want to achieve her is (in case - user is offline - and try to request a new page that isn't in cache, he should be redirected to the (offline.php) page which was saved in the static cache) like the following
// If both (network & cache) fail, show a generic fallback:
return caches.match('offline.php');
but i have a problem that i don't know where exactly should i add this line in my (sw.js) file within (fetch) step, i really tried reading more about service workers & Javascript promises and tried adding this line several times different place in my code, but every time neither make it work but misses up with the previous scenario or keep the scenario but fail to achieve this goal.
Really appreciate your kind help & many thanks in advance.
Using a Service worker you can easily set an app up to use cached assets first, thus providing a default experience even when offline, before then getting more data from the network (commonly known as Offline First).
A service worker intercepts network-type HTTP requests and uses a caching strategy to determine what resources should be returned to the browser.
We ll put the request into the caches - caches. put with the response clone returned from the fetch promise. Return the response. If promise got rejected fetch will go to caches (pre-cache) to match the request URL request.
In your fetch event listener:
.catch(function(err) {
// Fallback to cache
return caches.match(event.request);
})
caches.match(event.request) in fact returns a Promise that resolves to undefined if no match is found from the cache.
Check for undefined and return offline.php from cache:
return caches.match(event.request)
.then(function(res){
if (res === undefined) {
// get and return the offline page
}
return res;
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With