PWA Firebase Push Notifications "This site has been updated in the background " - javascript

I have been testing push notifications for a PWA(Progressive-Web-App) through Firebase but everytime i Recieve the notification it just says "Chrome Push Notification: This site has been updated in the background". I am testing it in localhost and tried testing similar answer but nothing seems to fix it.
And This is my serviceworker:
(function () {
'use strict';
// Update 'version' if you need to refresh the cache
var version = 'v1.0::CacheFirstSafe';
var offlineUrl = "Offline"; // <-- Offline/Index.cshtml
var urlsToCache = ['./', offlineUrl]; // <-- Add more URLs you would like to cache.
// Store core files in a cache (including a page to display when offline)
function updateStaticCache() {
return caches.open(version)
.then(function (cache) {
return cache.addAll(urlsToCache);
});
}
function addToCache(request, response) {
if (!response.ok && response.type !== 'opaque')
return;
var copy = response.clone();
caches.open(version)
.then(function (cache) {
cache.put(request, copy);
});
}
function serveOfflineImage(request) {
if (request.headers.get('Accept').indexOf('image') !== -1) {
return new Response('<svg role="img" aria-labelledby="offline-title" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title id="offline-title">Offline</title><g fill="none" fill-rule="evenodd"><path fill="#D8D8D8" d="M0 0h400v300H0z"/><text fill="#9B9B9B" font-family="Helvetica Neue,Arial,Helvetica,sans-serif" font-size="72" font-weight="bold"><tspan x="93" y="172">offline</tspan></text></g></svg>', { headers: { 'Content-Type': 'image/svg+xml' } });
}
}
self.addEventListener('install', function (event) {
event.waitUntil(updateStaticCache());
});
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) {
return key.indexOf(version) !== 0;
})
.map(function (key) {
return caches.delete(key);
})
);
})
);
});
self.addEventListener('fetch', function (event) {
var request = event.request;
// Always fetch non-GET requests from the network
if (request.method !== 'GET' || request.url.match(/\/browserLink/ig)) {
event.respondWith(
fetch(request)
.catch(function () {
return caches.match(offlineUrl);
})
);
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) {
event.respondWith(
fetch(request)
.then(function (response) {
// Stash a copy of this page in the cache
addToCache(request, response);
return response;
})
.catch(function () {
return caches.match(request)
.then(function (response) {
return response || caches.match(offlineUrl);
});
})
);
return;
}
// cache first for fingerprinted resources
if (request.url.match(/(\?|&)v=/ig)) {
event.respondWith(
caches.match(request)
.then(function (response) {
return response || fetch(request)
.then(function (response) {
addToCache(request, response);
return response || serveOfflineImage(request);
})
.catch(function () {
return serveOfflineImage(request);
});
})
);
return;
}
// network first for non-fingerprinted resources
event.respondWith(
fetch(request)
.then(function (response) {
// Stash a copy of this page in the cache
addToCache(request, response);
return response;
})
.catch(function () {
return caches.match(request)
.then(function (response) {
return response || serveOfflineImage(request);
})
.catch(function () {
return serveOfflineImage(request);
});
})
);
});
self.addEventListener('push', function (event) {
console.log('Received a push message', event);
var title = 'Yay a message.';
var body = 'We have received a push message.';
var icon = './Content/image/apple-icon-180x180.png';
var tag = 'simple-push-demo-notification-tag';
var data = {
doge: {
wow: 'such amaze notification data'
}
};
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag,
data: data
})
);
});
self.addEventListener('notificationclick', function (event) {
// here data you access from event using event.notification.data
console.log('On notification click: ', event.notification.tag);
});
})();

Related

how do i cache the large files on the browser to make the loading time faster

Im trying to store model and js files in cache storage using service workers to make the loading time fast but the cache is not being stored and fetched from the cache storage,when I change the version also it is not able to refetch the cache and store them,
self.addEventListener('fetch', function(event) {});
var CACHE_VERSION = 2.2
var CURRENT_CACHES = {
prefetch: 'prefetch-cache-v' + CACHE_VERSION
};
self.addEventListener('install', function(event) {
var urlsToPrefetch = [
'/',
'https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js',
'https://use.typekit.net/af/dde969/00000000000000007735b995/30/l?primer=7cdcb44be4a7db8877ffa5c0007b8dd865b3bbc383831fe2ea177f62257a9191&fvd=n7&v=3',
'https://cdn.jsdelivr.net/npm/#mediapipe/camera_utils/camera_utils.js',
'https://code.jquery.com/jquery-2.2.4.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js',
'https://cdn.jsdelivr.net/npm/#mediapipe/pose/pose_solution_packed_assets_loader.js',
'https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css',
'https://cdn.jsdelivr.net/npm/#mediapipe/pose/pose.js',
'https://cdn.jsdelivr.net/npm/#mediapipe/pose/pose_web.binarypb',
'https://cdn.jsdelivr.net/npm/#mediapipe/pose/pose_solution_packed_assets.data',
'https://cdn.jsdelivr.net/npm/#mediapipe/pose/pose_landmark_lite.tflite',
'https://cdn.jsdelivr.net/npm/#mediapipe/pose/pose_solution_simd_wasm_bin.wasm',
'https://cdn.jsdelivr.net/npm/#mediapipe/pose/pose_solution_simd_wasm_bin.js',
];
self.skipWaiting();
event.waitUntil(
caches.open(CURRENT_CACHES.prefetch).then(function(cache) {
return cache.addAll(urlsToPrefetch);
})
);
});
self.addEventListener('activate', function(event) {
var expectedCacheNames = Object.keys(CURRENT_CACHES).map(function(key) {
return CURRENT_CACHES[key];
});
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.map(function(cacheName) {
if (expectedCacheNames.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});
self.addEventListener('fetch', function(event) {
if (event.request.headers.get('range')) {
var pos =
Number(/^bytes\=(\d+)\-$/g.exec(event.request.headers.get('range'))[1]);
event.respondWith(
caches.open(CURRENT_CACHES.prefetch)
.then(function(cache) {
return cache.match(event.request.url);
}).then(function(res) {
if (!res) {
return fetch(event.request)
.then(res => {
return res.arrayBuffer();
});
}
return res.arrayBuffer();
}).then(function(ab) {
return new Response(
ab.slice(pos),
{
status: 206,
statusText: 'Partial Content',
headers: [
['Content-Range', 'bytes ' + pos + '-' +
(ab.byteLength - 1) + '/' + ab.byteLength]]
});
}));
} else {
event.respondWith(
caches.match(event.request).then(function(response) {
if (response) {
return response;
}
return fetch(event.request).then(function(response) {
return response;
}).catch(function(error) {
throw error;
});
})
);
}
});
for some reason it works better in linux system, if I do hard refresh it will work sometimes but the files is not fetched from the cache always,even thought the files can be seen in cache storage of the browser

Error in Service Worker: Cannot construct a Request with a Request object that has already been used

When the following service worker code runs I get a bunch of these errors:
serv-worker.js:38 Uncaught (in promise) TypeError: Failed to execute 'fetch' on 'WorkerGlobalScope': Cannot construct a Request with a Request object that has already been used.
Question also asked here and unanswered: [https://stackoverflow.com/questions/55979921/error-request-object-that-has-already-been-used]
Appreciations for any help/explanation!
console.log('Start serv-worker.js');
const cacheName = '3.2121';
var urlsToCache = [
'home.html',
'home-js.js',
'web-bg.js',
'css/main.css',
'css/edit-menus.css'
];
self.addEventListener('install', event => {
console.log('Install event...', urlsToCache);
event.waitUntil(
caches.open(cacheName)
.then(function(cache) {
console.log('Opened cache', cacheName);
return cache.addAll(urlsToCache);
})
);
});
// Network first.
self.addEventListener('fetch', (event) => {
// Check the cache first
// If it's not found, send the request to the network
// event.respondWith(
// caches.match(event.request).then(function (response) {
// return response || fetch(event.request).then(function (response) {
// return response;
// });
// })
// );
event.respondWith(async function() {
try {
console.log('aPull from network...', event.request);
return await fetch(event.request);
} catch (err) {
console.log('aPull from cache...', event.request);
return caches.match(event.request);
}
}());
});
self.addEventListener('message', function (event) {
console.log('ServiceWorker cache version: ', cacheName, event);
console.log('Received msg1: ', event.data);
if (event.data.action === 'skipWaiting') {
console.log('ccClearing cache: ', cacheName);
// caches.delete('1.9rt1'); // hardcode old one
// caches.delete(cacheName); // actually removes cached versions
caches.keys().then(function(names) {
for (let name of names)
caches.delete(name);
});
self.skipWaiting();
}
});

CSS not rendering in offline mode using Service Worker in Chrome

I'm trying to get my PWA to work in offline mode. So far, it's serving all the files from localhost, but the CSS doesn't render. All files requested from the cache are getting status 200. (javascript and html are fully functional) Here's my service-worker code.
self.addEventListener("install", (event) => {
event.waitUntil(
caches.open("v1").then((cache) => {
return cache.addAll([
"list of assets",
]);
})
);
});
self.addEventListener("fetch", function (event) {
event.respondWith(
caches.open("v1").then((cache) => {
if (event.request.url == "http://localhost:3000/") {
return cache
.match("http://localhost:3000/index.html")
.then((response) => {
console.log({ response });
return response;
});
} else {
try {
return cache.match(event.request).then((response) => {
console.log(response);
if (response != undefined) {
console.log({ response: "Loading asset from cache." });
return response;
} else {
let asset = fetch(event.request);
cache.add(asset);
return asset;
}
});
} catch (error) {
console.error(error);
}
}
})
);
});
Did you try listing your stylesheet where you have 'list of assets'?
return cache.addAll([
‘./css/styles.css'
]);

Is there any way that service worker can delete the cache on device on every website update?

Whenever I make any updates to my website, which is developed using Laravel, I have to delete the browser cache in order to reflect the changes. This is for both while working on localhost and when I deploy it on the server. Is there any way to automate the process, either by service worker where the cache is deleted after every new update?
Here is my serviceworker.js
var staticCacheName = "pwa-v" + new Date().getTime();
var filesToCache = [
'/offline.html',
'/css/style.css',
'/js/app.js',
];
// 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("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.html');
})
)
});
Here is a snippet I am using to delete stale assets without manual intervention.
function deleteStaleAssets(url, asset) {
caches.open(CACHE_NAME).then(function(cache) {
cache.keys().then(function(keys) {
let cc = keys.filter(function(req) {
if(req.url.includes(asset) && req.url !== url) {
return true;
}
});
cc.forEach(function(r) {
cache.delete(r);
});
});
});
}
function onFetch(event) {
var assets = ['/assets/application', 'assets/spree/frontend/all'];
var asset = assets.find(function(asset) {
return event.request.url.includes(asset);
});
if(asset) {
event.respondWith(async function() {
const cache = await caches.open(CACHE_NAME);
const cachedResponse = await cache.match(event.request);
const networkResponsePromise = fetch(event.request);
event.waitUntil(async function() {
const networkResponse = await networkResponsePromise;
deleteStaleAssets(event.request.url, asset);
await cache.put(event.request, networkResponse.clone());
}());
// Returned the cached response if we have one, otherwise return the network response.
return cachedResponse || networkResponsePromise;
}());
}
else {
event.respondWith(
// try to return untouched request from network first
fetch(event.request).catch(function() {
// if it fails, try to return request from the cache
return caches.match(event.request).then(function(response) {
if (response) {
return response;
}
// if not found in cache, return default offline content for navigate requests
if (event.request.mode === 'navigate' ||
(event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) {
return caches.match('/offline.html');
}
})
})
);
}
}

Offline page when offline and cache is deleted

My serviceworker looks like that :
const staticCacheName = 'restaurant-cache-v6';
const OFFLINE_URL = 'offline.html';
const filesToCache = [
'/',
'./manifest.json',
'./index.html',
'./offline.html',
'./restaurant.min.html',
'./css/styles.min.css',
'./js/lazyload.min.js',
'./js/idb.min.js',
'./js/dbhelper.min.js',
'./js/main.min.js',
'./js/restaurant_info.min.js',
'./data/restaurants.json',
'./img/1.jpg',
];
self.addEventListener('install', function (e) {
console.log('[ServiceWorker] Install');
e.waitUntil(caches.open(staticCacheName).then(function (cache) {
console.log('Cache is opened');
return cache.addAll(filesToCache);
})
);
});
self.addEventListener('active', function (e) {
e.waitUntil(
caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames.filter(function (cacheName) {
return cacheName.startsWith('restaurant-') && cacheName != staticCacheName;
}).map(function (cacheName) {
return caches.delete(cacheName);
})
);
}))
});
self.addEventListener('fetch', function (e) {
{
e.respondWith(
caches.match(e.request, { ignoreSearch: true }).then(function (res) {//now works with query string in the URL. !!!!
if (res) {
return res;
}
var fetchReq = e.request.clone();
return fetch(fetchReq).then(
function (res) {
if (!res || res.status !== 200 || res.type !== 'basic') {
return res;
}
var resToCache = res.clone();
caches.open(staticCacheName)
.then(function (cache) {
cache.put(e.request, resToCache);
});
return res;
}
);
})
);
}
});
self.addEventListener('message', function (e) {
if (e.data.action === 'skipWaiting') {
self.skipWaiting();
}
});
Everything works fine, sw registrations, when i switch in devtools offline its fetches from cache - my page looks like online
but when i'm going offline and clearing all cache i get :
Everything works fine, sw registrations, when i switch in devtools offline its fetches from cache - my page looks like online
but when i'm going offline and clearing all cache i get :
Is there a way to render OFFLINE_URL site from sw?

Categories