-
Notifications
You must be signed in to change notification settings - Fork 0
/
service-worker.js
168 lines (146 loc) · 6.57 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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
The service worker is a fundamental component for enabling a progressive web app to operate offline.
By caching essential files listed in the filesToCache.js script—automatically generated during the
project's build process—it ensures that these files are available from the cache when no network
connection is available.
During deployment, the build pipeline automatically relocates the service worker to the root
directory of the project. It also generates a config-sw.js file based on your project's config.js
file. This configuration specifies the cache version and outlines which paths should be excluded
from caching. The cache version, dictated by config.js, is pivotal for cache management and is
refreshed anytime there's a version update via the pipeline.
When handling requests to the database (indicated by URLs starting with "database/..."), the
service worker attempts to fetch the data from the network first. If the network request fails,
it looks for the data in the cache. Failing to find the data in the cache too, it returns a status
code of 503, signaling service unavailability. This approach ensures data availability, even in
offline scenarios, enhancing the user experience by leveraging modern web capabilities.
*/
self.CACHE_VERSION = "0.0.11.8";
importScripts('./config-sw.js' + `?v=${self.CACHE_VERSION}`);
self.importScripts('Birdhouse/filesToCache.js' + `?v=${self.CACHE_VERSION}`);
self.addEventListener('install', function (event) {
event.waitUntil(cacheFiles().then(() => self.skipWaiting()));
});
function cacheFiles() {
return caches.open(self.CACHE_VERSION).then(function (cache) {
const filesWithCacheVersion = filesToCache.map(file => `${file}?v=${self.CACHE_VERSION}`);
return cache.addAll(filesWithCacheVersion)
.catch(function (error) {
console.error('Error caching files:', error);
});
});
}
self.addEventListener('activate', function (event) {
event.waitUntil(
cacheFiles().then(() =>
caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames.map(function (cacheName) {
if (self.CACHE_VERSION !== cacheName) {
return caches.delete(cacheName);
}
})
);
}))
.then(() => self.clients.claim())
);
});
self.addEventListener('message', event => {
if (event.data && event.data.action === 'skipWaiting') {
self.skipWaiting();
}
});
self.addEventListener('fetch', function (event) {
var request = event.request;
if (self.config && self.config.excludedPaths && self.config.excludedPaths.some(path => request.url.includes(path))) {
event.respondWith(fetch(request));
return;
}
if (request.method === 'POST') {
event.respondWith(
fetch(request).catch(function () {
return new Response(JSON.stringify({ success: false, message: 'You are offline: This action cannot be performed' }), {
headers: { 'Content-Type': 'application/json' },
status: 503,
statusText: 'Service Unavailable'
});
})
);
return;
}
if (request.url.includes('database/')) {
event.respondWith(
fetch(request)
.then(function (response) {
var responseToCache = response.clone();
caches.open(self.CACHE_VERSION).then(function (cache) {
cache.put(request, responseToCache);
});
return response;
})
.catch(function () {
return caches.match(request)
.then(function (response) {
if (response) {
return response;
} else {
return new Response('You are offline: The requested data is not available', { status: 503 });
}
});
})
);
}
else {
var urlWithoutQuery = request.url;
if (event.request.mode === 'navigate') {
urlWithoutQuery = '/index.html';
}
var updatedRequest = new Request(urlWithoutQuery + `?v=${self.CACHE_VERSION}`, {
method: request.method,
headers: request.headers,
mode: 'cors',
credentials: request.credentials,
redirect: request.redirect,
referrer: request.referrer,
integrity: request.integrity
});
event.respondWith(
caches.match(updatedRequest, { ignoreSearch: false })
.then(function (response) {
if (response) {
return response;
}
if (request.url.includes('manifest.json')) {
return fetch(request)
.then(response => {
if (!response || response.status !== 200) {
console.error('Failed to fetch manifest.json');
throw new Error('Failed to fetch manifest.json');
}
return response;
})
.catch(error => {
console.error('Fetch failed for manifest.json', error);
throw error;
});
}
var fetchRequest = request.clone();
return fetch(fetchRequest).then(
function (response) {
if (!response || response.status !== 200) {
return response;
}
var responseToCache = response.clone();
caches.open(self.CACHE_VERSION)
.then(function (cache) {
cache.put(updatedRequest, responseToCache);
});
return response;
}
).catch(function () {
return caches.match(`/index.html?v=${self.CACHE_VERSION}`)
.catch(() => new Response('You are offline: This action cannot be performed'));
});
})
);
}
});