-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathservice-worker.js
More file actions
151 lines (140 loc) · 4.32 KB
/
service-worker.js
File metadata and controls
151 lines (140 loc) · 4.32 KB
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
const CACHE_NAME = 'pwa-cache-v1';
const OFFLINE_URL = '/404.html';
const urlsToCache = [
'/',
'/index.html',
'/contact.html',
'/contact-script.js',
'/articles.html',
'/articles-script.js',
'/projects.html',
'/projects-script.js',
'/interests.html',
'/interests-script.js',
'/skills.html',
'/skills-script.js',
'/career.html',
'/career-script.js',
'/articles/reflections-on-ai-and-coding.html',
'/articles/post-footer.html',
'/articles/post-footer.js',
'/faq.html',
'/faq-script.js',
'/404.html',
'/styles.css',
'/script.js',
'/partials/header.html',
'/partials/footer.html',
'/partials/sidebar.html',
'/partials/footer.js',
'/partials/header.js',
'/partials/sidebar.js',
'/manifest.json',
'/robots.txt',
'/sitemap.xml',
'/img/anapat_chairithinugull.jpeg',
'/icons/icon16.png',
'/icons/icon32.png',
'/icons/icon48.png',
'/icons/icon60.png',
'/icons/icon152.png',
'/icons/icon167.png',
'/icons/icon180.png',
'/icons/icon192.png',
'/icons/icon512.png'
];
// Helper: fetch and cache a request (same-origin only)
async function fetchAndCache(request) {
try {
const response = await fetch(request);
// only cache successful same-origin GET responses
if (response && response.ok && new URL(request.url).origin === location.origin) {
const cache = await caches.open(CACHE_NAME);
await cache.put(request, response.clone());
}
return response;
} catch (err) {
console.error('Fetch and cache error:', err);
return undefined;
}
}
// Install event — resilient caching
self.addEventListener('install', (event) => {
event.waitUntil((async () => {
const cache = await caches.open(CACHE_NAME);
// Fetch all resources and individually put successful responses into cache
const results = await Promise.allSettled(
urlsToCache.map(u => fetch(new Request(u, { cache: 'no-cache' })))
);
await Promise.all(results.map(async (r, i) => {
if (r.status === 'fulfilled' && r.value && r.value.ok) {
try {
await cache.put(urlsToCache[i], r.value.clone());
} catch (e) {
console.error(`Failed to cache ${urlsToCache[i]}:`, e);
}
}
}));
// Ensure fallback page cached if possible
try {
const offlineResp = await fetch(new Request(OFFLINE_URL, { cache: 'no-cache' }));
if (offlineResp && offlineResp.ok) await cache.put(OFFLINE_URL, offlineResp.clone());
} catch (err) {
console.error('Failed to cache offline page:', err);
}
})());
self.skipWaiting();
});
// Fetch event
self.addEventListener('fetch', event => {
if (event.request.method !== 'GET') return;
const reqUrl = new URL(event.request.url);
// For navigations (HTML pages) prefer network-first with offline fallback
if (event.request.mode === 'navigate') {
event.respondWith((async () => {
try {
// Try network first
const networkResponse = await fetchAndCache(event.request);
if (networkResponse) return networkResponse;
// If network fails, try cache
const cacheResponse = await caches.match(event.request);
if (cacheResponse) return cacheResponse;
// If both fail, return offline page
return await caches.match(OFFLINE_URL);
} catch (err) {
// Last resort - offline page
console.error('Navigation fetch failed:', err);
return await caches.match(OFFLINE_URL);
}
})());
return;
}
// For non-navigation requests, use cache-first strategy
event.respondWith((async () => {
try {
// Try cache first
const cacheResponse = await caches.match(event.request);
if (cacheResponse) return cacheResponse;
// If not in cache, try network
const networkResponse = await fetchAndCache(event.request);
if (networkResponse) return networkResponse;
// If both fail, return error
throw new Error('Resource not available');
} catch (err) {
console.error('Resource fetch failed:', err);
throw err;
}
})());
});
// Activate event - clean up old caches
self.addEventListener('activate', event => {
event.waitUntil((async () => {
const cacheNames = await caches.keys();
await Promise.all(
cacheNames
.filter(name => name !== CACHE_NAME)
.map(name => caches.delete(name))
);
await clients.claim();
})());
});