admin管理员组文章数量:1326308
I am using service workers to create an offline page for my website.
At the moment I am saving offline.html
into cache so that the browser can show this file if there is no interent connection.
In the fetch
event of my service worker I attempt to load index.html
, and if this fails (no internet connection) I load offline.html
from cache.
However, whenever I check offline mode in developer tools and refresh the page index.html
still shows...
The request isn't failing, and it looks like index.html
is being cached even though I didn't specify it to be.
Here is my HTML for index.html
:
<!DOCTYPE html>
<html>
<head>
<title>Service Workers - Test</title>
</head>
<body>
<h1> Online page! </h1>
<h3> You are connected to the internet. </h3>
</body>
<script>
if ('serviceWorker' in navigator)
{
navigator.serviceWorker.register('service-worker.js');
}
</script>
</html>
Here is my HTML for offline.html
:
<!DOCTYPE html>
<html>
<head>
<title>You are Offline - Service Workers - Test</title>
</head>
<body>
<h1> Wele to the Offline Page!</h1>
<h2> You are not connected to the internet but you can still do certain things offline. </h2>
</body>
</html>
Here is my javascript for service-worker.js
:
const PRECACHE = "version1"
const CACHED = ["offline.html"];
// Caches "offline.html" incase there is no internet
self.addEventListener('install', event => {
console.log("[Service Worker] Installed");
caches.delete(PRECACHE)
event.waitUntil (
caches.open(PRECACHE)
.then(cache => cache.addAll(CACHED))
.then( _ => self.skipWaiting())
);
});
// Clears any caches that do not match this version
self.addEventListener("activate", event => {
event.waitUntil (
caches.keys()
.then(keys => {
return Promise.all (
keys.filter(key => {
return !key.startsWith(PRECACHE);
})
.map(key => {
return caches.delete(key);
})
);
})
.then(() => {
console.log('[Service Worker] Cleared Old Cache');
})
);
});
this.addEventListener('fetch', function(event) {
if (event.request.method !== 'GET') return;
console.log("[Service Worker] Handling Request ");
// If the request to `index.html` works it shows it, but if it fails it shows the cached version of `offline.html`
// This isn't working because `fetch` doesn't fail when there is no internet for some reason...
event.respondWith (
fetch(event.request)
.then(response => {
console.log("[Service Worker] Served from NETWORK");
return response;
}, () => {
console.log("[Service Worker] Served from CACHE");
return catches.match(event.request.url + OFFLINE_URL);
})
);
});
I am running a server using python's simple http server like so:
python -m SimpleHTTPServer
Does anyone know why the offline page isn't working and how I can fix this?
Thanks for the help, David
EDIT:
These images are showing that index.html
(localhost) is still loading without internet which means it must be cached.
Edit 2:
I've tried to add no-cache
to the fetch of index.html
and it still is fetching index.html
when I have offline checked.
fetch(event.request, {cache: "no-cache"}) ...
I am using service workers to create an offline page for my website.
At the moment I am saving offline.html
into cache so that the browser can show this file if there is no interent connection.
In the fetch
event of my service worker I attempt to load index.html
, and if this fails (no internet connection) I load offline.html
from cache.
However, whenever I check offline mode in developer tools and refresh the page index.html
still shows...
The request isn't failing, and it looks like index.html
is being cached even though I didn't specify it to be.
Here is my HTML for index.html
:
<!DOCTYPE html>
<html>
<head>
<title>Service Workers - Test</title>
</head>
<body>
<h1> Online page! </h1>
<h3> You are connected to the internet. </h3>
</body>
<script>
if ('serviceWorker' in navigator)
{
navigator.serviceWorker.register('service-worker.js');
}
</script>
</html>
Here is my HTML for offline.html
:
<!DOCTYPE html>
<html>
<head>
<title>You are Offline - Service Workers - Test</title>
</head>
<body>
<h1> Wele to the Offline Page!</h1>
<h2> You are not connected to the internet but you can still do certain things offline. </h2>
</body>
</html>
Here is my javascript for service-worker.js
:
const PRECACHE = "version1"
const CACHED = ["offline.html"];
// Caches "offline.html" incase there is no internet
self.addEventListener('install', event => {
console.log("[Service Worker] Installed");
caches.delete(PRECACHE)
event.waitUntil (
caches.open(PRECACHE)
.then(cache => cache.addAll(CACHED))
.then( _ => self.skipWaiting())
);
});
// Clears any caches that do not match this version
self.addEventListener("activate", event => {
event.waitUntil (
caches.keys()
.then(keys => {
return Promise.all (
keys.filter(key => {
return !key.startsWith(PRECACHE);
})
.map(key => {
return caches.delete(key);
})
);
})
.then(() => {
console.log('[Service Worker] Cleared Old Cache');
})
);
});
this.addEventListener('fetch', function(event) {
if (event.request.method !== 'GET') return;
console.log("[Service Worker] Handling Request ");
// If the request to `index.html` works it shows it, but if it fails it shows the cached version of `offline.html`
// This isn't working because `fetch` doesn't fail when there is no internet for some reason...
event.respondWith (
fetch(event.request)
.then(response => {
console.log("[Service Worker] Served from NETWORK");
return response;
}, () => {
console.log("[Service Worker] Served from CACHE");
return catches.match(event.request.url + OFFLINE_URL);
})
);
});
I am running a server using python's simple http server like so:
python -m SimpleHTTPServer
Does anyone know why the offline page isn't working and how I can fix this?
Thanks for the help, David
EDIT:
These images are showing that index.html
(localhost) is still loading without internet which means it must be cached.
Edit 2:
I've tried to add no-cache
to the fetch of index.html
and it still is fetching index.html
when I have offline checked.
fetch(event.request, {cache: "no-cache"}) ...
Share
Improve this question
edited Aug 2, 2017 at 11:51
David Callanan
asked Aug 1, 2017 at 20:41
David CallananDavid Callanan
5,82015 gold badges76 silver badges123 bronze badges
6
- 1 Is the worker throwing any warnings and/or errors? Is it installed? Can you see the cache in dev tools? under the application tab? – Schrodinger's cat Commented Aug 2, 2017 at 9:23
-
@Schrodinger'scat The service worker is installed and I refreshed the page again to make sure the service worker handled the fetch of the page. In the cache there was
index.html
even though I didn't cache it. – David Callanan Commented Aug 2, 2017 at 9:35 -
Ok! Among other things to look for, you have typos it is
caches.match
on the fetch event and notcatches
. Also, If you have anupdate on reload
checked, uncheck it, as when you go offline, the browser searches for a new service worker and the request fails.. – Schrodinger's cat Commented Aug 2, 2017 at 11:04 -
@Schrodinger'scat I've fixed all my typos but that didn't fix it. When I refresh the page it loads
index.html
which means that page must be cached even when I didn't include it in my cache listCACHED
– David Callanan Commented Aug 2, 2017 at 11:19 -
It looks like the index.html is served from disk cache and bypasses the service worker for some reason - noticed this after trying this out on my machine - This can be circumvented by checking
disable cache
, but that is a hack – Schrodinger's cat Commented Aug 2, 2017 at 13:34
3 Answers
Reset to default 4I think we have all forgotten how the network request works from a browser's point of view.
The issue here is, index.html
is served from the disk cache when the service worker intercepts requests.
browser ===> Service Worker ===>fetch event
inside the fetch event, we have ,
- Check If there is network connectivity
- If there is, fetch from network and respond
- Else, fetch from cache and respond
Now, how does
If there is network connectivity, fetch from network work?
Service Worker OnFetch ===> Check in Disk Cache ===>Nothing? Fetch Online
The page being fetched here, is index.html
and the cache-control
headers for index.html
,
Do Not Specify a no-cache
Hence the whole issue of the offline page not showing up.
Solution
- Set a
cache-control
header with limiting values forindex.html
- On the server side Or, add headers in the fetch request to the effect
pragma:no-cache
cache-control:no-cache
How Do I add these headers to fetch?
Apparently, fetch and the browser have their own reservations about the request body when it es to a GET
Also, weirdness and utter chaos happens If you reuse the event.request
object, for a fetch request, and add custom headers.
The chaos is a list of Uncaught Exceptions
due to the fetch
event's request.mode
attribute , which bars you from adding custom headers to a fetch when under a no-cors or a navigate mode.
Our goal is to :
Identify that the browser is truly offline and then serve a page that says so
Here's How:
Check If you can fetch a dummy html page say
test-connectivity.html
under your origin, with a customcache: no-cache
header. If you can, proceed, else throw the offline page
self.addEventListener( 'fetch', ( event ) => {
let headers = new Headers();
headers.append( 'cache-control', 'no-cache' );
headers.append( 'pragma', 'no-cache' );
var req = new Request( 'test-connectivity.html', {
method: 'GET',
mode: 'same-origin',
headers: headers,
redirect: 'manual' // let browser handle redirects
} );
event.respondWith( fetch( req, {
cache: 'no-store'
} )
.then( function ( response ) {
return fetch( event.request )
} )
.catch( function ( err ) {
return new Response( '<div><h2>Uh oh that did not work</h2></div>', {
headers: {
'Content-type': 'text/html'
}
} )
} ) )
} );
The {cache:'no-store'}
object as the second parameter to fetch
, is an unfortunate NO-OP. Just doesn't work.
Just keep it for the sake of a future scenario. It is really optional as of today.
If that worked, then you do not need to build a whole new Request
object for fetch
cheers!
The code piece that creates a new request is generously borrowed from @pirxpilot 's answer here
The offline worker for this specific question on pastebin
https://pastebin./sNCutAw7
David, you have two errors in one line.
Your line
return catches.match(event.request.url + OFFLINE_URL);
should be
return caches.match('offline.html');
It's catches
and you haven't defined OFFLINE_URL
and you don't need event request url
I tried your code and I got the same result as you in the dev tools network tab. The network tab says it loaded the index.html from service-worker, but actually the service-worker returns the cached Offline Page as expected!
本文标签: pythonJavascriptService Workers not working correctlyStack Overflow
版权声明:本文标题:python - Javascript - Service Workers not working correctly - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742205660a2432766.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论