-
Notifications
You must be signed in to change notification settings - Fork 0
/
service-worker.js
111 lines (104 loc) · 4.66 KB
/
service-worker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/* Many ideas here are based on: https://googlechrome.github.io/samples/service-worker/custom-offline-page/ */
/* Incrementing OFFLINE_VERSION (or any other change in this file) 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';
/* The page to serve if offline. */
const OFFLINE_PAGE_URL = '/offline.html';
/* All resources needed for the offline page. */
const OFFLINE_RESOURCE_URLS = [
OFFLINE_PAGE_URL,
'/styles/styles.css',
'/assets/favicon.ico',
'/assets/favicon-32x32.png',
'/assets/favicon-16x16.png',
'/assets/android-chrome-192x192.png',
];
const OFFLINE_RESOURCE_REQUESTS = [];
for (const OFFLINE_RESOURCE_URL of OFFLINE_RESOURCE_URLS) {
/* 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. */
OFFLINE_RESOURCE_REQUESTS.push(new Request(OFFLINE_RESOURCE_URL, {cache: 'reload'}));
}
self.addEventListener('install', (event) => {
console.log('[SW] ------------ install event ------------');
/* Kick out the current active worker and activate the new one as soon as it enters the waiting phase
See https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#skip_the_waiting_phase */
self.skipWaiting();
event.waitUntil((async () => {
const cache = await caches.open(CACHE_NAME);
await cache.addAll(OFFLINE_RESOURCE_REQUESTS);
})());
});
self.addEventListener('activate', (event) => {
console.log('[SW] ------------ 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();
}
})());
});
self.addEventListener('fetch', (event) => {
console.log('[SW] ------------ fetch event ------------');
/* Ignore non-GET requests */
if (event.request.method !== 'GET') {
return;
}
console.log(`[SW] fetch url: ${event.request.url}`);
/* We only want to call event.respondWith() if this is a navigation request for an HTML page.
All requests for an HTML page have to go through this service worker fetch handling to get the
offline state, which is handled in the catch. */
if (event.request.headers.get('Accept').includes('text/html')) {
console.log('[SW] HTML fetch');
event.respondWith((async () => {
console.log(`[SW] HTML fetch: service worker is handling this request`);
try {
/* First, try to use the navigation preload response if it's supported. */
const preloadResponse = await event.preloadResponse;
if (preloadResponse) {
console.log(`[SW] HTML fetch: preload response`);
return preloadResponse;
}
const fetchResponse = await fetch(event.request);
console.log(`[SW] HTML fetch: network response`);
return fetchResponse;
} 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. */
const cache = await caches.open(CACHE_NAME);
const cachedOfflinePage = await cache.match(OFFLINE_PAGE_URL);
console.log(`[SW] HTML fetch: cached response`);
return cachedOfflinePage;
}
})());
} else {
console.log(`[SW] none-HTML fetch`);
/* Check if the current request should have been cached. */
let isCachedResource = false;
for (const OFFLINE_RESOURCE_URL of OFFLINE_RESOURCE_URLS) {
if (event.request.url.includes(OFFLINE_RESOURCE_URL)) {
isCachedResource = true;
}
}
if (isCachedResource) {
event.respondWith((async () => {
console.log(`[SW] none-HTML fetch: service worker is handling this request`);
const cache = await caches.open(CACHE_NAME);
const cachedResponse = await cache.match(event.request.url);
console.log(`[SW] none-HTML fetch: cached response`);
return cachedResponse;
})());
} else {
// 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.
console.log(`[SW] none-HTML fetch: service worker is NOT handling this request`);
}
}
});