My service worker is not rendering the offline.html page that I have created. It's just showing the real web page before clearing cache. After clearing cache it is showing the usual connection lost page in offline mode instead of showing the offline.html page I have created. I have unregistered it one time. That's the reason for it. I'm attaching the screenshot of serviceworker.js file here: serviceworker.js.
It is a react app I converted to PWA.
Here is my serviceworker.js:
const CACHE_NAME = "version-1";
const urlsToCache = ["index.html", "offline.html"];
const self = this;
//installing SW
self.addEventListener("install", event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
console.log("Opened Cache")
return cache.addAll(urlsToCache)
})
)
})
//fetching request
self.addEventListener("fetch", event => {
event.respondWith(
caches.match(event.request)
.then(() => {
return fetch(event.request)
.catch(() => caches.match("offline.html"))
})
)
})
//activating SW
self.addEventListener("activate", event => {
const cacheWhiteList = [];
cacheWhiteList.push(CACHE_NAME)
event.waitUntil(
caches.keys()
.then(cacheNames => Promise.all(
cacheNames.map(cacheName => {
if (!-cacheWhiteList.includes(cacheName)) {
return caches.delete(cacheName)
}
})
))
)
})
Related
Am working on PWA and am trying to make my App works offline, so i cache my assets and its works fine, i could even use my app through my cached assets, BUT the problem is whenever i delete my cache using dev tools or whenever i update something in my assets my app not regenerate the cache again, how to regenrate the cache everytime when i start using the app online
Service worker registeration (app.js):
if('serviceWorker' in navigator){
navigator.serviceWorker.register('./sw.js')
.then((reg) => console.log('Service worker registered', reg))
.catch((err) => console.log('Service worker not registered', err));
}
My service worker looks like this:
const cacheName = 'VSCode_SG_' + Date.now(),
assets = [
'./',
'./app.min.js',
'./favicon.ico',
'./style.css',
];
self.addEventListener('install', evt => {
evt.waitUntil(caches.open(cacheName).then(cache => {
cache.addAll(assets);
}))
});
self.addEventListener('activate', evt => {
// Get all the currently active `Cache` instances.
evt.waitUntil(caches.keys().then((keys) => {
// Delete all caches that aren't in the allow list:
return Promise.all(keys.map((key) => {
if (!cacheName.includes(key)) {
return caches.delete(key);
}
}));
}));
});
self.addEventListener('fetch', evt => {
evt.respondWith(
caches.match(evt.request).then(cacheRes => {
return cacheRes || fetch(evt.request);
}).catch(() => console.log('An error has occurred'))
);
});
am sure that am missing a small detail to solve the problem but i don't have any clues, anyone could help?
I think your issue might be related to your caches name, you want it to stay a static name instead of labeling it with a date stamp
const cacheName = 'VSCode_SG_STATIC', // keep it a constant string
assets = [
'./',
'./app.min.js',
'./favicon.ico',
'./style.css',
];
Give this a shot and wait until your new service worker is installed to try again
When I try to access http://localhost/visites/ it should fetch the precached file visites/index.php . So I guess I have to indicate somewhere that this particular route matches that file, do you have any idea on how I can do that?
I leave my SW code here just in case:
const cacheName = 'v1';
const cacheAssets = [
'accueil.php',
'js/accueil.js',
'visites/index.php',
'js/visites.js',
'js/global.js',
'css/styles.css',
'charte/PICTOS/BTN-Visites.png',
'charte/STRUCTURE/GESTEL-Logo.png',
'charte/PICTOS/BTN-Animaux.png',
'charte/PICTOS/BTN-Deconnexion.png',
'charte/PICTOS/BTN-Fermes.png',
];
// Call Install Event
self.addEventListener('install', e => {
console.log('Service Worker: Installed');
e.waitUntil(
caches
.open(cacheName)
.then(cache => {
console.log('Service Worker: Caching Files');
cache.addAll(cacheAssets);
})
.then(() => self.skipWaiting())
);
});
// Call Activate Event
self.addEventListener('activate', e => {
console.log('Service Worker: Activated');
// Remove unwanted caches
e.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cache => {
if (cache !== cacheName) {
console.log('Service Worker: Clearing Old Cache');
return caches.delete(cache);
}
})
);
})
);
});
// Call Fetch Event
self.addEventListener('fetch', e => {
console.log('Service Worker: Fetching');
e.respondWith(fetch(e.request).catch(() => caches.match(e.request)));
})
You can include some logic in your fetch handler that accounts for this routing information:
self.addEventListener('fetch', e => {
// Use a URL object to simplify checking the path.
const url = new URL(e.request.url);
// Alternatively, check e.request.mode === 'navigate' if
// you want to match a navigation to any URL on your site.
if (url.pathname === '/visites/') {
e.respondWith(caches.match('visites/index.php'));
// Return after responding, so that the existing
// logic doesn't get triggered.
return;
}
e.respondWith(fetch(e.request).catch(() => caches.match(e.request)));
});
I have migrated my existing website to PWA.
My website is very simple made using HTML, JQuery and javascript.
Previously the caching mechanism was dependent on manifest.appcache.
Now when I try to cache the files using service worker none of the file are getting cached.
I have checked my service worker is registered and everything seems fine but files are not getting stored in cache.
I tried clearing the cache but no help.
I am sharing my service worker code below since it is production code I can not share all file names.
I used this site to learn PWA.
const staticCacheName = 'site-static-v4';
const dynamicCacheName = 'site-dynamic-v4';
const assets = [
"index.shtml",
"fallback.html",
"manifest.webmanifest"
];
// cache size limit function
const limitCacheSize = (name, size) => {
caches.open(name).then(cache => {
cache.keys().then(keys => {
if(keys.length > size){
cache.delete(keys[0]).then(limitCacheSize(name, size));
}
});
});
};
// install event
self.addEventListener('install', evt => {
//console.log('service worker installed');
evt.waitUntil(
caches.open(staticCacheName).then((cache) => {
console.log('caching shell assets');
cache.addAll(assets);
})
);
});
// activate event
self.addEventListener('activate', evt => {
//console.log('service worker activated');
evt.waitUntil(
caches.keys().then(keys => {
//console.log(keys);
return Promise.all(keys
.filter(key => key !== staticCacheName && key !== dynamicCacheName)
.map(key => caches.delete(key))
);
})
);
});
// fetch event
self.addEventListener('fetch', evt => {
//console.log('fetch event', evt);
evt.respondWith(
caches.match(evt.request).then(cacheRes => {
return cacheRes || fetch(evt.request).then(fetchRes => {
return caches.open(dynamicCacheName).then(cache => {
cache.put(evt.request.url, fetchRes.clone());
// check cached items size
limitCacheSize(dynamicCacheName, 15);
return fetchRes;
})
});
}).catch(() => {
if(evt.request.url.indexOf('.html') > -1){
return caches.match('fallback.html');
}
})
);
});
Below is the screenshot of my empty cache storage.
I am learning how to implement PWAs and understand the underlying concept thus far. My problem is when I am trying to cache static assets in my service worker file, nothing is actually being cached and this error is fired instead.
Uncaught (in promise) TypeError: Request failed
Below is my code.
const staticAssets = [
'./',
'./index.php',
'./account.php',
'./css/account.css',
'./css/bootstrap-4.0.0.css',
'./css/bootstrap.min.css',
'./css/common.css',
'./css/dashboard.css',
'./css/fonts.css',
'./css/home.css',
'./lib/Magnific-Popup/dist/magnific-popup.css', ,
'./lib/sweetalerts/sweetalert.css',
'./images/logo.png',
'./repository/images/*.png',
'./repository/images/*.jpg',
'./repository/images/*.gif',
'./js/account.jsx',
'./js/app.jsx',
'./js/bootstrap-4.0.0.js',
'./js/dashboard.jsx',
'./js/jquery-3.2.1.min.js',
'./js/popper.min.js',
'./js/project.jsx',
'./js/security.jsx',
'./lib/Magnific-Popup/dist/jquery.magnific-popup.min.js',
'./lib/Magnific-Popup/dist/jquery.magnific-popup.js',
'./lib/sweetalerts/sweetalert.min.js',
'./lib/sweetalerts/sweetalert.js'
];
self.addEventListener("install", async event => {
const cache = await caches.open("mystatic-assets");
cache.addAll(staticAssets);
});
self.addEventListener("fetch", event => {
const req = event.request;
event.respondWith(cacheFirst(req));
});
async function cacheFirst(req) {
const cacheResponse = await caches.match(req);
return cacheResponse || fetch(req);
}```
What am I doing wrong?
First of all i have to mention if there is an error or typo in the paths you provide as static URLs it will fail and will not cache anything.
1/ try this
self.addEventListener("install", event => {
event.waitUntil(
caches.open("mystatic-assets").then(cache => {
cache.addAll(staticAssets);
})
);
});
secondly
in your fetch event
self.addEventListener("fetch", event => {
const req = event.request;
event.respondWith(cacheFirst(req));
});
function cacheFirst(req) {
return chaches.match(req) || fetch(req)
}
try this and tell me
I have been working on pwa project and i opened two cache
one is static-cache and another one is dynamic-cache i am able to delete one cache at a time by using this code
self.addEventListener('activate', event => {
console.log('Activating new service worker...');
const cacheWhitelist = [staticCacheName];
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});
i want to delete both caches at same time
Your code looks already good. In my case, I use the following code to delete the SW caches:
if ('caches' in window) {
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.filter(cacheName => {
// You can have some custom logic here, if you want
// to delete only some caches
// If you return TRUE, the cache will be deleted
}).map(cacheName => {
return caches.delete(cacheName);
})
);
})
}
The caches.keys() method returns the keys of the CacheStorage, an interface representing the storage for the Cache objects that can be accessed by the service worker.
I wrote an article about service workers and caching strategies, if you want to deepen the topic.
Not an expert but I think using filter like this will work.
cacheNames.filter(cacheName => {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
try this:
self.addEventListener( "activate", event => {
event.waitUntil(
//wholesale purge of previous version caches
caches.keys().then( cacheNames => {
cacheNames.forEach( value => {
caches.delete( value );
} );
} );
} );