I have added service worker and workbox as following
In template file:
<script type="text/javascript">
(function () {
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('sw.js')
.then(function(registration) {
console.log('Service Worker registration successful with scope: ',
registration.scope);
})
.catch(function(err) {
console.log('Service Worker registration failed: ', err);
});
}
})();
</script>
And in sw.js, I have
importScripts('workbox-sw.prod.v2.1.2.js');
const workboxSW = new WorkboxSW();
if (workboxSW) {
console.log('Yay! workboxSW is loaded');
const staleWhileRevalidateStrategy = workboxSW.strategies.staleWhileRevalidate();
workboxSW.router.registerRoute('/*\.css/', staleWhileRevalidateStrategy);
} else {
console.log('Boo! workboxSW didn\'t load');
}
I can see in the console log that "Service Worker registration successful" and "Yay! workboxSW is loaded". But I don't see anything under cache storage (Application -> Cache Storage). How can I update it so that I can see cache content by the service worker?
Related
I hava a pwa with this sw.js:
const info = "versione: 1.0.0 data: 07-01-2020 12:46";
const CACHE = "pwa-offline";
const pages = [
// some files
];
self.addEventListener("install", function (event) {
//console.log("Install Event processing");
self.skipWaiting();
event.waitUntil(
caches.open(CACHE).then(function (cache) {
//console.log("Cached offline page during install");
return cache.addAll(pages);
})
);
});
self.addEventListener("activate", (event) => {
});
self.addEventListener("fetch", function (event) {
if (event.request.method !== "GET") return;
event.respondWith(
fetch(event.request)
.then(function (response) {
return fromCache(event.request);
})
.catch(function (error) {
//console.log("Network request Failed. Serving content from cache: " + error);
return fromCache(event.request);
})
);
});
async function fromCache(request) {
// Check to see if you have it in the cache
// Return response
// If not in the cache, then return error page
const cache = await caches.open(CACHE);
const matching = await cache.match(request);
if (!matching || matching.status === 404) {
return Promise.reject("no-match");
}
return matching;
}
async function updateCache(request, response) {
const cache = await caches.open(CACHE);
return cache.put(request, response);
}
and index.html with this code inside:
<script>
if ("serviceWorker" in navigator) {
navigator.serviceWorker
.register("./sw.js")//, {updateViaCache: 'none'})
.then(reg => {
//console.log("Registration successful", reg);
})
.catch(e =>
console.error("Error during service worker registration:", e)
);
} else {
console.warn("Service Worker is not supported");
}
</script>
I upload the pwa in a firebase site. When I change the sw.js (e.g. changing the date of versionDate, in this site https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle I read: "Your service worker is considered updated if it's byte-different to the one the browser already has. (We're extending this to include imported scripts/modules too.)") and I upload, I see the new service worker is changed. But when I make a second change in sw.js and upload, the sw.js is not changed, so I can do only an update on sw.js and so to the whole site (because the sw.js caches all files of the site during the install process).
How can I update my site any time I want?
UPDATE: I watched that the problem is in android phone in desktop is ok.
UPDATE: Now also it works on android but the update is not immadiate. I see the update after some hours.
Your service worker caches all static files on your website. Consequently, you will need to edit your sw.js file whenever you are updating your website. One common way to do this is to attach a version number to your static cache name, for example pwa-offline-v1, then bump up the version number in the sw.js file whenever you are pushing an update to the site. This creates a new cache and stores the updated static files to it. You can then add an activate event listener on the service worker to delete the former cache using a function like this.
const info = "versione: 1.0.0 data: 07-01-2020 12:46";
const CACHE = "pwa-offline-v1";
const pages = [
// some files
];
self.addEventListener("install", function (event) {
//console.log("Install Event processing");
self.skipWaiting();
event.waitUntil(
caches.open(CACHE).then(function (cache) {
//console.log("Cached offline page during install");
return cache.addAll(pages);
})
);
});
self.addEventListener("activate", (event) => {
event.waitUntil(
Promise.all(
caches.keys().then((cacheNames) => {
cacheNames
.filter(cacheName => cacheName.startsWith('pwa-offline-') && cacheName !== CACHE)
.map(cacheName => caches.delete(cacheName))
})
)
);
});
I have a site with a service worker and it registers every time a new sub-URL is visited. Is this the expected behaviour?
Example. My root URL is mysite.com. The SW registers OK when I visit that URL. When I visit mysite.com/subpage, it registers as a new service worker for that URL too.
Please tell me if I am doing something wrong or if this is the way the SWs work.
My service worker recache the resources everytime it installs, so I'm guessing it is recaching everything everytime the user visits a sub-URL for the first time. Isn't that not recommended?
This is my SW.
var staticCacheName = "bspev-v" + new Date().getTime();
var filesToCache = [
'/',
'/offline',
'/css/app.css',
'/js/app.js',
'/js/rutas.js',
// iconos app
'/images/icons/icon-72x72.png',
'/images/icons/icon-96x96.png',
'/images/icons/icon-128x128.png',
'/images/icons/icon-144x144.png',
'/images/icons/icon-152x152.png',
'/images/icons/icon-192x192.png',
'/images/icons/icon-384x384.png',
'/images/icons/icon-512x512.png',
'/favicon.ico',
// imagenes app
'/images/logotexto.png',
'/images/offline.png',
// ajax
'/api/prestamos/pendientes',
//fuentes app
'https://fonts.googleapis.com/css?family=Archivo+Narrow&display=swap',
'https://fonts.gstatic.com/s/archivonarrow/v11/tss0ApVBdCYD5Q7hcxTE1ArZ0bbwiXw.woff2',
// vue
'/js/vue.js',
'/js/vue.min.js',
// fontawesome
'/css/fa-all.css',
'/webfonts/fa-solid-900.woff2'
];
// Cache on install
self.addEventListener("install", event => {
this.skipWaiting();
event.waitUntil(
caches.open(staticCacheName)
.then(cache => {
console.log('Service Worker instalado.');
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("bspev-")))
.filter(cacheName => (cacheName !== staticCacheName))
.map(cacheName => caches.delete(cacheName))
);
})
);
});
// Serve from Cache
self.addEventListener("fetch", event => {
const requestURL = new URL(event.request.url);
//Handle api calls
if (/\/api\//.test(requestURL.pathname)) {
event.respondWith(
fetch(event.request).then(response => {
event.waitUntil(
caches.open(staticCacheName).then(cache => {
cache.put(event.request, response.clone());
})
);
return response.clone();
}).catch(function() {
return caches.match(event.request);
})
);
} else {
event.respondWith(
caches.match(event.request)
.then(response => {
return response || fetch(event.request);
})
.catch(() => {
return caches.match('offline');
})
);
}
});
This is the SW registration
<script type="text/javascript">
// Initialize the service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/serviceworker.js', {
scope: '.'
}).then(function (registration) {
// Registration was successful
console.log('Laravel PWA: ServiceWorker registration successful with scope: ', registration.scope);
}, function (err) {
// registration failed :(
console.log('Laravel PWA: ServiceWorker registration failed: ', err);
});
} else { console.log('no serviceWorker in navigator') }
</script>
SW caches an image file, but not JS (size 0 bytes)
/*serviceWorker*/
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('service-worker.js', { scope: '/' })
.then(function(registration) {
console.log("Service Worker Registered");
})
.catch(function(err) {
console.log("Service Worker Failed to Register", err);
})
};
const CACHE = 'cache-only-v1';
const timeout = 400;
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE).then((cache) => {
return cache.addAll([
'/sys/Raycaster/3d.js',
'/sys/js/popmotion.global.min.js',
'/sys/js/anime.min.js',
'sys/b/bgFeedback.jpg',
'/sys/b/ic.svg',
'/sys/b/ani/img_ani_1.webp',
'/sys/b/ani/img_ani_2.webp',
'/sys/b/ani/img_ani_3.webp',
'/sys/printProd/p.webp',
'/sys/printProd/p2.webp',
'/sys/printProd/p3.webp',
'/sys/printProd/p4.webp',
'/sys/printProd/p5.webp',
'/sys/printProd/p6.webp',
'/sys/printProd/p7.webp',
'/sys/printProd/p8.webp',
'/sys/printProd/p9.webp',
'/sys/printProd/p10.webp',
'/sys/printProd/p11.webp',
'/sys/printProd/p12.webp',
'/sys/sliderInSlider/01_el.webp',
'/sys/sliderInSlider/02_dv.webp',
'/sys/sliderInSlider/05_snth.webp',
'/sys/sliderInSlider/06_ton.webp',
'/sys/sliderInSlider/07_pty.webp',
'/sys/sliderInSlider/08_lyu.webp',
'/sys/sliderInSlider/09_kar.webp'
]);
})
);
});
Image here: https://f.usemind.org/img/2019-05-28_143451.jpg
Information displayed in chrome DevTools are based on Response Headers and sometimes, it doesn't reflect reality. Your js files are cached but it doesn't have a Content-Lenght in it's Headers.
to test it you can do :
caches.open(CACHES)
.then( cache => cache.match('/sys/js/popmotion.global.min.js'))
.then( res =>res.text())
.then( js => console.log(js))
This code will check in your caches for popmotion.global.min.js, and display it's content.
I am trying to get aServiceWorker to work from a subdirectory in webroot named appdashboard ... the serviceworker installs, runs and is visible from chrome://serviceworker-internals/, but its Navigator.serviceWorker.controller is null so I cannot communicate with it. If I don't restrict the scope (and move my serviceworker file to webroot) it works fine.
const serviceWorker = navigator
.serviceWorker
.register('appdashboard/dashboard_serviceworker.js', { scope: 'http://localhost/appdashboard/' })
.then((swReg) => {
console.log('[Service Worker (Dashboard)] service worker is registered', swReg);
swRegistration = swReg;
if (navigator.serviceWorker.controller != null) {
console.log("controller is working")
}
if (navigator.serviceWorker.controller == null) {
console.log("controller is NULL!") // <<<< its null :(
}
})
I simplified my serviceworker as much as possible to diagnose the issue, and controller is null even with this bare bones worker
self.addEventListener('message', function (event) {
console.log('got message')
});
self.addEventListener('activate', function (event) {
console.log('serviceworker activate')
event.waitUntil(self.clients.claim()); // Become available to all pages
});
self.addEventListener('install', function (event) {
console.log('install')
});
self.addEventListener('fetch', function (event) {
console.log('fetch')
});
self.addEventListener('push', (event) => {
console.log('received push')
});
self.addEventListener('notificationclick', function (event) {
console.log('registered notification click!')
});
I was using MVC routing so that my URL path was localhost/dashboard but my file structure was /appdashboard/, now I serve up an index.html from /appdashboard/ webroot and controller initializes.
This is the line that set me on the right path.
Remember the scope, when included, uses the page's location as its
base. Alternatively, if this code were included in a page at
example.com/product/description.html, the scope of './' would mean
that the service worker only applies to resources under
example.com/product.
I have a service worker running and registered - it adds a bunch of files to the "static cache" - as files are initiated / requested - they are dynamically added to the cache - it's running and working fine - however, I notice that the live data in the html is not being updated - I used Dev tools to investigate further and noticed that eventsource and xhr were being cached by the service worker - however fetch requests aren't. has anyone else come across this / found a solution?
var CACHE_STATIC_NAME = 'static-v1';
var CACHE_DYNAMIC_NAME = 'dynamic-v1';
self.addEventListener('install', function(event) {
console.log('[Service Worker] Installing Service Worker ...', event);
event.waitUntil(
caches.open(CACHE_STATIC_NAME)
.then(function(cache) {
console.log('[Service Worker] Precaching App Shell');
cache.addAll([
'index.html',
'CSS/style.css',
'CSS/style-responsive.css',
'CSS/default-theme.css',
'fonts/fontawesome-webfont.woff',
'IMAGES/company.png',
'IMAGES/icon.png',
'IMAGES/bg.png',
'IMAGES/header.png',
'CSS/Icons/Android/48.png',
'app.js' ]);
})
);
});
self.addEventListener('activate', function(event) {
console.log('[Service Worker] 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('[Service Worker] Removing old cache.', key);
return caches.delete(key);
}
}));
})
);
return self.clients.claim();
});
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
if (response) {
return response;
} else {
return fetch(event.request)
.then(function(res) {
return caches.open(CACHE_DYNAMIC_NAME)
.then(function(cache) {
cache.put(event.request.url, res.clone());
return res;
})
})
.catch(function(err) {
});
}
})
);
});