Service worker update not working? - javascript

I have a nginx hosted Jekyll site.
I have made several changes to my site, update package version and changed my javascript to update the service worker. However my changes are still not reflecting in chrome;
main.js
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js', {scope: 'sw-test'}).then(function(registration) {
// registration worked
console.log('Registration succeeded.');
registration.update();
}).catch(function(error) {
// registration failed
console.log('Registration failed with ' + error)
});
}
sw.js
var PRECACHE = 'precache-{{site.version}}';
var RUNTIME = 'runtime';
// A list of local resources we always want to be cached.
var PRECACHE_URLS = [
'./',
'/index.html',
'/assets/css/main.css',
'/assets/js/vendor/modernizr-custom.js',
'/assets/js/bundle.js'
];
// The install handler takes care of precaching the resources we always need.
self.addEventListener('install', event => {
event.waitUntil(
caches.open(PRECACHE)
.then(cache => cache.addAll(PRECACHE_URLS))
.then(self.skipWaiting())
);
});
// The activate handler takes care of cleaning up old caches.
self.addEventListener('activate', event => {
var currentCaches = [PRECACHE, RUNTIME];
event.waitUntil(
caches.keys().then(cacheNames => {
return cacheNames.filter(cacheName => !currentCaches.includes(cacheName));
}).then(cachesToDelete => {
return Promise.all(cachesToDelete.map(cacheToDelete => {
return caches.delete(cacheToDelete);
}));
}).then(() => self.clients.claim())
);
});
// The fetch handler serves responses for same-origin resources from a cache.
// If no response is found, it populates the runtime cache with the response
// from the network before returning it to the page.
self.addEventListener('fetch', event => {
// Skip cross-origin requests, like those for Google Analytics.
if (event.request.url.startsWith(self.location.origin)) {
event.respondWith(
caches.match(event.request).then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
}
return caches.open(RUNTIME).then(cache => {
return fetch(event.request).then(response => {
// Put a copy of the response in the runtime cache.
return cache.put(event.request, response.clone()).then(() => {
return response;
});
});
});
})
);
}
});
Chrome Screenshot
Screenshot
Any help greatly appreciated!!

Your nginx config is most likely setting some caching headers on the SW script. When that's the case, the browser returns the old version from its local cache skipping network completely.

Related

Service Worker (sw.js) should always return offline.html document if there is no network connection

I'm having an issue with a service worker that's working partially. The manifest defines the start_url correctly (https://example.com/start.html) for users that add the website to the Homescreen, and both the start.html and offline.html are cached correctly as well, and both are available while the browser has no internet connection.
If the user gets offline (no network connection), the service worker successfully serves both https://example.com/start.html and https://example.com/offline.html -- but if the user tries opening anything else (e.g. https://example.com/something.html) the browser throws a "site can't be reached" error message.
What I actually need, is that, if there is no network connection, the service worker always returns the offline.html cached document, no matter which url the user is trying to reach.
In other words, the problem is that the Service Worker is not properly serving offline.html for the user's requests when there's no network connection (whatever solution is found, it also needs to cache the start.html for the manifest's start_url).
This is my current code:
manifest.json
{
"name": "My Basic Example",
"short_name": "Example",
"icons": [
{
"src": "https://example.com/static/ico/manifest-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "https://example.com/static/ico/manifest-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}
],
"start_url": "https://example.com/start.html",
"scope": "/",
"display": "standalone",
"orientation": "portrait",
"background_color": "#2196f3",
"theme_color": "#2196f3"
}
core.js
if('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js', {
scope: '/'
}).then(function(registration) {
}).catch(function(err) {
});
navigator.serviceWorker.ready.then(function(registration) {
});
}
sw.js
const PRECACHE = 'cache-v1';
const RUNTIME = 'runtime';
const PRECACHE_URLS = [
'/offline.html',
'/start.html'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(PRECACHE)
.then(cache => cache.addAll(PRECACHE_URLS))
.then(self.skipWaiting())
);
});
self.addEventListener('activate', event => {
const currentCaches = [PRECACHE, RUNTIME];
event.waitUntil(
caches.keys().then(cacheNames => {
return cacheNames.filter(cacheName => !currentCaches.includes(cacheName));
})
.then(cachesToDelete => {
return Promise.all(cachesToDelete.map(cacheToDelete => {
return caches.delete(cacheToDelete);
}));
})
.then(() => self.clients.claim())
);
});
self.addEventListener('fetch', event => {
if(event.request.url.startsWith(self.location.origin)) {
event.respondWith(
caches.match(event.request).then(cachedResponse => {
if(cachedResponse) {
return cachedResponse;
}
return caches.open(RUNTIME).then(cache => {
return fetch(event.request).then(response => {
return cache.put(event.request, response.clone()).then(() => {
return response;
});
});
});
})
);
}
});
Any ideas? Thanks!
Most of your code worked as expected, but you needed a check to see if the user was requesting start.html. I took the code from Create an offline fallback page and modified it to suit your request.
// Incrementing OFFLINE_VERSION will kick off the install event and force
// previously cached resources to be updated from the network.
const OFFLINE_VERSION = 1;
const CACHE_NAME = "offline";
// Customize this with a different URL if needed.
const START_URL = "start.html";
const OFFLINE_URL = "offline.html";
self.addEventListener("install", (event) => {
event.waitUntil(
(async () => {
const cache = await caches.open(CACHE_NAME);
// Setting {cache: 'reload'} in the new request will ensure that the
// response isn't fulfilled from the HTTP cache; i.e., it will be from
// the network.
await Promise.all([
cache.add(new Request(OFFLINE_URL, { cache: "reload" })),
cache.add(new Request(START_URL, { cache: "reload" })),
]);
})()
);
// Force the waiting service worker to become the active service worker.
self.skipWaiting();
});
self.addEventListener("activate", (event) => {
event.waitUntil(
(async () => {
// Enable navigation preload if it's supported.
// See https://developers.google.com/web/updates/2017/02/navigation-preload
if ("navigationPreload" in self.registration) {
await self.registration.navigationPreload.enable();
}
})()
);
// Tell the active service worker to take control of the page immediately.
self.clients.claim();
});
self.addEventListener("fetch", (event) => {
// We only want to call event.respondWith() if this is a navigation request
// for an HTML page.
if (event.request.mode === "navigate") {
event.respondWith(
(async () => {
try {
// First, try to use the navigation preload response if it's supported.
const preloadResponse = await event.preloadResponse;
if (preloadResponse) {
return preloadResponse;
}
// Always try the network first.
const networkResponse = await fetch(event.request);
return networkResponse;
} catch (error) {
// catch is only triggered if an exception is thrown, which is likely
// due to a network error.
// If fetch() returns a valid HTTP response with a response code in
// the 4xx or 5xx range, the catch() will NOT be called.
console.log("Fetch failed; returning cached page instead.", error);
const cache = await caches.open(CACHE_NAME);
if (event.request.url.includes(START_URL)) {
return await cache.match(START_URL);
}
return await cache.match(OFFLINE_URL);
}
})()
);
}
// If our if() condition is false, then this fetch handler won't intercept the
// request. If there are any other fetch handlers registered, they will get a
// chance to call event.respondWith(). If no fetch handlers call
// event.respondWith(), the request will be handled by the browser as if there
// were no service worker involvement.
});
One thing to note with this, once start.html has been cached when the service worker is first installed, it will not be updated again until the service worker is updated. That means your users may see an old/outdated start.html any time they're offline and load your app. You probably want to use a network first strategy for start.html.
You can try the working demo and source

Service worker offline page won't load

This used to work for me but stopped a couple of months ago and I've tinkered my way right out of being able to figure this out anymore. What am I doing wrong here?
Call the service worker template, no problem:
if(navigator.serviceWorker){
window.addEventListener('load',() => {
navigator.serviceWorker
.register('/sw.js')
.then(console.log('[ServiceWorker] Registered Successfully'))
.catch(err => console.log(`[ServiceWorker] Error: ${err}`));
});
} else {
console.log('Service Worker not supported.');
}
Setup a cache version and preloaded the cache, no problem:
const cacheName='2020.10.06-01';
var cacheFiles = ['/offline.html'];
Installed the Services Worker, no problem:
addEventListener('install', e => {
e.waitUntil(
caches.open(cacheName).then(cache => {
return cache.addAll(cacheFiles);
})
);
});
Activated the Services Worker for auto cache rollover, no problem:
addEventListener('activate', e => {
e.waitUntil(
caches.keys().then(keyList => {
return Promise.all(keyList.map(key => {
if(key !== cacheName) {
return caches.delete(key);
}
}));
})
);
});
Fetching from cache or network, no problem:
addEventListener('fetch', e => {
e.respondWith(async function() {
try {
const cache = await caches.open(cacheName);
const cachedResponse = await cache.match(e.request);
const networkResponsePromise = fetch(e.request);
e.waitUntil(async function() {
const networkResponse = await networkResponsePromise;
await cache.put(e.request, networkResponse.clone());
}());
// Returned the cached response if we have one, otherwise return the network response.
return cachedResponse || networkResponsePromise;
} catch (error) {
console.log('Fetch failed; returning offline page instead.', error);
const cache = await caches.open(cacheName);
const cachedResponse = await cache.match('/offline.html');
return cachedResponse;
}
}());
});
But if the page/resource I'm trying to request is not already in the cache AND the network is not available it refuses to display my 'offline.html' page. (Which I know IS in the cache)
Any ideas?
Here's the Fetch code I wrote in the end that works perfectly for me:
self.addEventListener('fetch', (event) => {
event.respondWith((async() => {
const cache = await caches.open(cacheName);
try {
const cachedResponse = await cache.match(event.request);
if(cachedResponse) {
console.log('cachedResponse: ', event.request.url);
return cachedResponse;
}
const fetchResponse = await fetch(event.request);
if(fetchResponse) {
console.log('fetchResponse: ', event.request.url);
await cache.put(event.request, fetchResponse.clone());
return fetchResponse;
}
} catch (error) {
console.log('Fetch failed: ', error);
const cachedResponse = await cache.match('/en/offline.html');
return cachedResponse;
}
})());
});
This does everything I need, in a very specific order. It checks the cache first, if found it's returned. It checks the network next, if found it caches it first then returns it. Or it displays a custom offline page with a big Reload button to encourage visitors to try again when they are back online.
But the most important this to realise is that doing it this way alows me to display a page and all it's resources with or without network access.
UPDATE: In order to deal with changes to CORS security requirements that where implemented in all browsers between March and August of 2020, I had to make one small change to the 'fetch' event.
Changed from:
const fetchResponse = await fetch(event.request);
To:
const fetchResponse = await fetch(event.request, {mode:'no-cors'});
Replace your fetch event code with this one. For every request your fetch event will be invoked and it will check if your request is found in the cache file list then it will serve the file from there otherwise it will make the fetch call to get the file from server.
self.addEventListener("fetch", function (event) {
event.respondWith(
caches.match(event.request)
.then(function (response) {
if (response) {
return response;
}
return fetch(event.request);
})
);
});
Also you don't need a separate "offline.html" file in your cache file list. Instead add your main application html file and your relevant css and js files in that list. That will make your application completely offline in case of no network.

Workbox update cache on new version

I have implemented Workbox to generate my service worker using webpack.
This works pretty well - I can confirm that revision is updated in the generated service worker when running yarn run generate-sw (package.json: "generate-sw": "workbox inject:manifest").
The problem is - I have noticed my clients are not updating the cache after a new release.
Even days after updating the service worker my clients are still caching the old code and new code will only cache after several refreshes and/or unregister the service worker.
For each release the const CACHE_DYNAMIC_NAME = 'dynamic-v1.1.0' is updated.
How can I ensure that clients updates the cache immediately after a new release?
serviceWorker-base.js
importScripts('workbox-sw.prod.v2.1.3.js')
const CACHE_DYNAMIC_NAME = 'dynamic-v1.1.0'
const workboxSW = new self.WorkboxSW()
// Cache then network for fonts
workboxSW.router.registerRoute(
/.*(?:googleapis)\.com.*$/,
workboxSW.strategies.staleWhileRevalidate({
cacheName: 'google-font',
cacheExpiration: {
maxEntries: 1,
maxAgeSeconds: 60 * 60 * 24 * 28
}
})
)
// Cache then network for css
workboxSW.router.registerRoute(
'/dist/main.css',
workboxSW.strategies.staleWhileRevalidate({
cacheName: 'css'
})
)
// Cache then network for avatars
workboxSW.router.registerRoute(
'/img/avatars/:avatar-image',
workboxSW.strategies.staleWhileRevalidate({
cacheName: 'images-avatars'
})
)
// Cache then network for images
workboxSW.router.registerRoute(
'/img/:image',
workboxSW.strategies.staleWhileRevalidate({
cacheName: 'images'
})
)
// Cache then network for icons
workboxSW.router.registerRoute(
'/img/icons/:image',
workboxSW.strategies.staleWhileRevalidate({
cacheName: 'images-icons'
})
)
// Fallback page for html files
workboxSW.router.registerRoute(
(routeData)=>{
// routeData.url
return (routeData.event.request.headers.get('accept').includes('text/html'))
},
(args) => {
return caches.match(args.event.request)
.then((response) => {
if (response) {
return response
}else{
return fetch(args.event.request)
.then((res) => {
return caches.open(CACHE_DYNAMIC_NAME)
.then((cache) => {
cache.put(args.event.request.url, res.clone())
return res
})
})
.catch((err) => {
return caches.match('/offline.html')
.then((res) => { return res })
})
}
})
}
)
workboxSW.precache([])
// Own vanilla service worker code
self.addEventListener('notificationclick', function (event){
let notification = event.notification
let action = event.action
console.log(notification)
if (action === 'confirm') {
console.log('Confirm was chosen')
notification.close()
} else {
const urlToOpen = new URL(notification.data.url, self.location.origin).href;
const promiseChain = clients.matchAll({ type: 'window', includeUncontrolled: true })
.then((windowClients) => {
let matchingClient = null;
let matchingUrl = false;
for (let i=0; i < windowClients.length; i++){
const windowClient = windowClients[i];
if (windowClient.visibilityState === 'visible'){
matchingClient = windowClient;
matchingUrl = (windowClient.url === urlToOpen);
break;
}
}
if (matchingClient){
if(!matchingUrl){ matchingClient.navigate(urlToOpen); }
matchingClient.focus();
} else {
clients.openWindow(urlToOpen);
}
notification.close();
});
event.waitUntil(promiseChain);
}
})
self.addEventListener('notificationclose', (event) => {
// Great place to send back statistical data to figure out why user did not interact
console.log('Notification was closed', event)
})
self.addEventListener('push', function (event){
console.log('Push Notification received', event)
// Default values
const defaultData = {title: 'New!', content: 'Something new happened!', openUrl: '/'}
const data = (event.data) ? JSON.parse(event.data.text()) : defaultData
var options = {
body: data.content,
icon: '/images/icons/manifest-icon-512.png',
badge: '/images/icons/badge128.png',
data: {
url: data.openUrl
}
}
console.log('options', options)
event.waitUntil(
self.registration.showNotification(data.title, options)
)
})
Should I delete the cache manually or should Workbox do that for me?
caches.keys().then(cacheNames => {
cacheNames.forEach(cacheName => {
caches.delete(cacheName);
});
});
Kind regards /K
I think your problem is related to the fact that when you make an update to the app and deploy, new service worker gets installed, but not activated. Which explains the behaviour why this is happening.
The reason for this is registerRoute function also registers fetch listeners , but those fetch listeners won't be called until new service worker kicks in as activated. Also, the answer to your question: No, you don't need to remove the cache by yourself. Workbox takes care of those.
Let me know more details. When you deploy new code, and if users close all the tabs of your website and open a new one after that, does it start working after 2 refreshes? If so , that's how it should be working. I will update my answer after you provide more details.
I'd suggest you read the following: https://redfin.engineering/how-to-fix-the-refresh-button-when-using-service-workers-a8e27af6df68 and follow the 3rd approach.
One way to get WorkBox to update when you have the files locally, not on a CDN, is the following way:
In your serviceworker.js file add an event listener so that WorkBox skips waiting when there is an update, my code looks like this:
importScripts('Scripts/workbox/workbox-sw.js');
if (workbox) {
console.log('Workbox is loaded :)');
// Add a message listener to the waiting service worker
// instructing it to skip waiting on when updates are done.
addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
skipWaiting();
}
});
// Since I am using Local Workbox Files Instead of CDN I need to set the modulePathPrefix as follows
workbox.setConfig({ modulePathPrefix: 'Scripts/workbox/' });
// other workbox settings ...
}
In your client side page add an event listener for loads if service worker is in the navigator. As a note I am doing this in MVC so I put my code in the _Layout.cshtml so that it can update from any page on my website.
<script type="text/javascript">
if ('serviceWorker' in navigator) {
// Use the window load event to keep the page load performant
window.addEventListener('load', () => {
navigator.serviceWorker
// register WorkBox, our ServiceWorker.
.register("<PATH_TO_YOUR_SERVICE_WORKER/serviceworker.js"), { scope: '/<SOME_SCOPE>/' })
.then(function (registration) {
/**
* Whether WorkBox cached files are being updated.
* #type {boolean}
* */
let updating;
// Function handler for the ServiceWorker updates.
registration.onupdatefound = () => {
const serviceWorker = registration.installing;
if (serviceWorker == null) { // service worker is not available return.
return;
}
// Listen to the browser's service worker state changes
serviceWorker.onstatechange = () => {
// IF ServiceWorker has been installed
// AND we have a controller, meaning that the old chached files got deleted and new files cached
// AND ServiceWorkerRegistration is waiting
// THEN let ServieWorker know that it can skip waiting.
if (serviceWorker.state === 'installed' && navigator.serviceWorker.controller && registration && registration.waiting) {
updating = true;
// In my "~/serviceworker.js" file there is an event listener that got added to listen to the post message.
registration.waiting.postMessage({ type: 'SKIP_WAITING' });
}
// IF we had an update of the cache files and we are done activating the ServiceWorker service
// THEN let the user know that we updated the files and we are reloading the website.
if (updating && serviceWorker.state === 'activated') {
// I am using an alert as an example, in my code I use a custom dialog that has an overlay so that the user can't do anything besides clicking okay.
alert('The cached files have been updated, the browser will re-load.');
window.location.reload();
}
};
};
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}).catch(function (err) {
//registration failed :(
console.log('ServiceWorker registration failed: ', err);
});
});
} else {
console.log('No service-worker on this browser');
}
</script>
Note: I used the browser's service worker to update my WorkBox cached files, also, I've only tested this in Chrome, I have not tried it in other browsers.

Django + Service Workers: "a redirected response was used for a request whose redirect mode is not follow" error

I've been trying to build a progressive Django Web App with a service worker and django-pwa. Everything seems to work fine, but whenever I load the page, turn on offline mode in Chrome, and reload, I get this error:
"The FetchEvent for "https://haverford.getdibs.app/login/?redirect_to=/dashboard/" resulted in a network error response: a redirected response was used for a request whose redirect mode is not "follow"".
Now I've seen that someone else came into a seemingly similar problem here, but I don't quite understand what's going on in the answer. I think I need to set the redirect mode to "follow" for a request that I make with my fetch, but I'm not sure how to do that.
Here is my service worker:
var staticCacheName = "django-pwa-v" + new Date().getTime();
var filesToCache = [
'/offline',
];
// Cache on install
self.addEventListener("install", event => {
this.skipWaiting();
event.waitUntil(
caches.open(staticCacheName)
.then(cache => {
return cache.addAll(filesToCache);
})
)
});
// Clear cache on activate
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames
.filter(cacheName => (cacheName.startsWith("django-pwa-")))
.filter(cacheName => (cacheName !== staticCacheName))
.map(cacheName => caches.delete(cacheName))
);
})
);
});
// Serve from Cache
self.addEventListener("fetch", event => {
event.respondWith(
caches.match(event.request)
.then(response => {
return response || fetch(event.request);
})
.catch(() => {
return caches.match('offline');
})
)
});
I'm under the impression that i somehow have to make the event.request's redirect mode to 'follow', but when I put a breakpoint in that line and examine the event.request object, its redirect is set to 'manual'. How would I change it?
Any help in my quest to understanding what the issue actually is would be much appreciated.
Thank you.
Thanks a lot, sideshowbarker.
Method 1 in this link helped solve my problem.
I replaced my install event from this:
self.addEventListener("install", event => {
this.skipWaiting();
event.waitUntil(
caches.open(staticCacheName)
.then(cache => {
return cache.addAll(filesToCache);
})
)
});
to this:
self.addEventListener("install", event => {
this.skipWaiting();
event.waitUntil(
caches.open(staticCacheName)
.then(cache => {
return fetch('/offline')
.then(response => cache.put('/offline', new Response(response.body)));
})
)
});
Of course, right now it only works for that one URL endpoint ('/offline'), but it would be similar for multiple fetch requests I suppose.

Progressive web app Uncaught (in promise) TypeError: Failed to fetch

I started learning PWA (Progressive Web App) and I have problem, console "throws" error Uncaught (in promise) TypeError: Failed to fetch.
Anyone know what could be the cause?
let CACHE = 'cache';
self.addEventListener('install', function(evt) {
console.log('The service worker is being installed.');
evt.waitUntil(precache());
});
self.addEventListener('fetch', function(evt) {
console.log('The service worker is serving the asset.');
evt.respondWith(fromCache(evt.request));
});
function precache() {
return caches.open(CACHE).then(function (cache) {
return cache.addAll([
'/media/wysiwyg/homepage/desktop.jpg',
'/media/wysiwyg/homepage/bottom2_desktop.jpg'
]);
});
}
function fromCache(request) {
return caches.open(CACHE).then(function (cache) {
return cache.match(request).then(function (matching) {
return matching || Promise.reject('no-match');
});
});
}
I think this is due to the fact that you don't have a fallback strategy. event.respondWith comes with a promise which you have to catch if there's some error.
So, I'd suggest that you change your code from this:
self.addEventListener('fetch', function(evt) {
console.log('The service worker is serving the asset.');
evt.respondWith(fromCache(evt.request));
});
To something like this:
addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
if (response) {
return response; // if valid response is found in cache return it
} else {
return fetch(event.request) //fetch from internet
.then(function(res) {
return caches.open(CACHE_DYNAMIC_NAME)
.then(function(cache) {
cache.put(event.request.url, res.clone()); //save the response for future
return res; // return the fetched data
})
})
.catch(function(err) { // fallback mechanism
return caches.open(CACHE_CONTAINING_ERROR_MESSAGES)
.then(function(cache) {
return cache.match('/offline.html');
});
});
}
})
);
});
NOTE: There are many strategies for caching, what I've shown here is offline first approach. For more info this & this is a must read.
I found a solution to the same error, in my case the error showed when the service worker could not find a file*, fix it by following the network in dev tool of chrome session, and identified the nonexistent file that the service worker did not find and removed array of files to register.
'/processos/themes/base/js/processos/step/Validation.min.js',
'/processos/themes/base/js/processos/Acoes.min.js',
'/processos/themes/base/js/processos/Processos.min.js',
'/processos/themes/base/js/processos/jBPM.min.js',
'/processos/themes/base/js/highcharts/highcharts-options-white.js',
'/processos/themes/base/js/publico/ProcessoJsController.js',
// '/processos/gzip_457955466/bundles/plugins.jawrjs',
// '/processos/gzip_N1378055855/bundles/publico.jawrjs',
// '/processos/gzip_457955466/bundles/plugins.jawrjs',
'/mobile/js/about.js',
'/mobile/js/access.js',
*I bolded the solution for me... I start with just a file for cache and then add another... till I get the bad path to one, also define the scope {scope: '/'} or {scope: './'} - edit by lawrghita
I had the same error and in my case Adblock was blocking the fetch to an url which started by 'ad' (e.g. /adsomething.php)
In my case, the files to be cached were not found (check the network console), something to do with relative paths, since I am using localhost and the site is inside a sub-directory because I develop multiple projects on a XAMPP server.
So I changed
let cache_name = 'Custom_name_cache';
let cached_assets = [
'/',
'index.php',
'css/main.css',
'js/main.js'
];
self.addEventListener('install', function (e) {
e.waitUntil(
caches.open(cache_name).then(function (cache) {
return cache.addAll(cached_assets);
})
);
});
To below: note the "./" on the cached_assets
let cache_name = 'Custom_name_cache';
let cached_assets = [
'./',
'./index.php',
'./css/main.css',
'./js/main.js'
];
self.addEventListener('install', function (e) {
e.waitUntil(
caches.open(cache_name).then(function (cache) {
return cache.addAll(cached_assets);
})
);
});
Try to use / before adding or fetching any path like /offline.html or /main.js
Cached files reference should be correct otherwise the fetch will fail. Even if one reference is incorrect the whole fetch will fail.
let cache_name = 'Custom_name_cache';
let cached_files = [
'/',
'index.html',
'css/main.css',
'js/main.js'
];
// The reference here should be correct.
self.addEventListener('install', function (e) {
e.waitUntil(
caches.open(cache_name).then(function (cache) {
return cache.addAll(cached_files);
})
);
});

Categories

Resources