Skip to content

Commit 4a03388

Browse files
committed
fix offline mode
1 parent 0b9a6c1 commit 4a03388

1 file changed

Lines changed: 88 additions & 60 deletions

File tree

public/sw.js

Lines changed: 88 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@ self.addEventListener('install', (event) => {
1515
event.waitUntil(
1616
caches.open(STATIC_CACHE).then(cache => {
1717
console.log('Caching static assets');
18-
const assets = [
19-
'/',
20-
'/index.html'
21-
];
22-
return cache.addAll(assets).catch(err => {
18+
return cache.addAll(STATIC_ASSETS).catch(err => {
2319
console.warn('Some static assets failed to cache:', err);
2420
});
2521
})
@@ -49,52 +45,39 @@ self.addEventListener('activate', (event) => {
4945
self.addEventListener('fetch', (event) => {
5046
const url = new URL(event.request.url);
5147

52-
// Don't intercept non-GET requests to our own origin (they should go directly)
53-
if (url.origin === location.origin && event.request.method !== 'GET') {
48+
// Handle all GitHub API requests for any method
49+
if (url.origin === GITHUB_API_BASE) {
50+
event.respondWith(handleGitHubRequest(event.request));
5451
return;
5552
}
5653

57-
// Handle all GitHub API requests
58-
if (url.origin === GITHUB_API_BASE) {
59-
event.respondWith(handleGitHubRequest(event.request));
54+
if (event.request.method !== 'GET') {
6055
return;
6156
}
6257

63-
// Allow external resources to pass through without caching scripts
64-
// Only handle if method is GET
65-
if (event.request.method === 'GET') {
66-
// For gravatar images - cache them, but let umnico and other scripts pass through
67-
if ((url.hostname.includes('gravatar.com') || url.hostname.includes('www.gravatar.com')) &&
68-
event.request.destination === 'image') {
69-
event.respondWith(
70-
caches.open(EXTERNAL_CACHE).then(cache => {
71-
return cache.match(event.request).then(cached => {
72-
return fetch(event.request)
73-
.then(response => {
74-
if (response && response.status === 200) {
75-
cache.put(event.request, response.clone());
76-
}
77-
return response;
78-
})
79-
.catch(() => cached || new Response('', { status: 204 }));
80-
});
81-
})
82-
);
83-
return;
84-
}
58+
// Handle external gravatar images separately to support offline avatar caching
59+
if ((url.hostname === 'gravatar.com' || url.hostname === 'www.gravatar.com') &&
60+
event.request.destination === 'image') {
61+
event.respondWith(handleGravatarRequest(event.request));
62+
return;
63+
}
8564

86-
// For umnico and other external resources - network only, don't cache scripts
87-
if (url.hostname.includes('umnico.com') || url.hostname.includes('www.umnico.com')) {
88-
event.respondWith(
89-
fetch(event.request)
90-
.catch(() => new Response('', { status: 204 }))
91-
);
92-
return;
93-
}
65+
// Allow umnico scripts to load from network, but don't block the app
66+
if (url.hostname === 'umnico.com' || url.hostname === 'www.umnico.com') {
67+
event.respondWith(
68+
fetch(event.request).catch(() => new Response('', { status: 204 }))
69+
);
70+
return;
71+
}
9472

95-
// Handle static assets with network-first strategy
96-
event.respondWith(handleStaticRequest(event.request));
73+
// Handle page navigation and app shell requests
74+
if (event.request.mode === 'navigate' || event.request.headers.get('accept')?.includes('text/html')) {
75+
event.respondWith(handleNavigationRequest(event.request));
76+
return;
9777
}
78+
79+
// Handle same-origin or other static GET requests
80+
event.respondWith(handleStaticRequest(event.request));
9881
});
9982

10083
// Handle GitHub API requests - cache-first for offline support
@@ -105,12 +88,7 @@ async function handleGitHubRequest(request) {
10588
// For GET requests, check cache first
10689
if (request.method === 'GET') {
10790
const cache = await caches.open(GITHUB_API_CACHE);
108-
const cacheKey = new Request(request.url, {
109-
method: 'GET',
110-
headers: new Headers({ Accept: 'application/vnd.github+json' })
111-
});
112-
113-
const cachedResponse = await cache.match(cacheKey);
91+
const cachedResponse = await cache.match(request.url);
11492
if (cachedResponse) {
11593
return cachedResponse.clone();
11694
}
@@ -157,29 +135,28 @@ async function handleGitHubRequest(request) {
157135
}
158136
}
159137

160-
// Handle static requests - network-first, fallback to cache
138+
// Handle static requests - cache-first, fallback to network
161139
async function handleStaticRequest(request) {
140+
const cache = await caches.open(STATIC_CACHE);
141+
const cachedResponse = await cache.match(request);
142+
if (cachedResponse) {
143+
return cachedResponse.clone();
144+
}
145+
162146
try {
163147
const response = await fetch(request);
164148
if (response.ok) {
165-
const cache = await caches.open(STATIC_CACHE);
166149
cache.put(request, response.clone()).catch(err => {
167150
console.warn('Failed to cache response:', err);
168151
});
169152
return response;
170153
}
171154
throw new Error('Network response not ok');
172155
} catch (error) {
173-
const cached = await caches.match(request);
174-
if (cached) {
175-
return cached;
176-
}
177-
178-
const navigationFallback = request.mode === 'navigate' || (request.headers.get('accept')?.includes('text/html'));
179-
if (navigationFallback) {
180-
const shell = await caches.match('/index.html');
156+
if (request.mode === 'navigate' || request.headers.get('accept')?.includes('text/html')) {
157+
const shell = await cache.match('/index.html');
181158
if (shell) {
182-
return shell;
159+
return shell.clone();
183160
}
184161
}
185162

@@ -190,10 +167,61 @@ async function handleStaticRequest(request) {
190167
}
191168
}
192169

170+
// Handle navigation requests with app shell fallback
171+
async function handleNavigationRequest(request) {
172+
const cache = await caches.open(STATIC_CACHE);
173+
const shell = await cache.match('/index.html');
174+
if (shell) {
175+
return shell.clone();
176+
}
177+
178+
try {
179+
const response = await fetch(request);
180+
if (response.ok) {
181+
cache.put(request, response.clone()).catch(err => {
182+
console.warn('Failed to cache navigation response:', err);
183+
});
184+
return response;
185+
}
186+
} catch (error) {
187+
console.warn('Navigation fetch failed:', error);
188+
}
189+
190+
return new Response('Offline - App shell unavailable', {
191+
status: 503,
192+
statusText: 'Service Unavailable'
193+
});
194+
}
195+
196+
// Handle Gravatar image requests with cache-first strategy
197+
async function handleGravatarRequest(request) {
198+
const cache = await caches.open(EXTERNAL_CACHE);
199+
const cachedResponse = await cache.match(request);
200+
if (cachedResponse) {
201+
return cachedResponse.clone();
202+
}
203+
204+
try {
205+
const response = await fetch(request);
206+
if (response.ok) {
207+
cache.put(request, response.clone()).catch(err => {
208+
console.warn('Failed to cache gravatar image:', err);
209+
});
210+
return response;
211+
}
212+
throw new Error('Network response not ok');
213+
} catch (error) {
214+
if (cachedResponse) {
215+
return cachedResponse.clone();
216+
}
217+
return new Response('', { status: 204 });
218+
}
219+
}
220+
193221
// Try to return cached version when offline
194222
async function tryOfflineFallback(request) {
195223
const cache = await caches.open(GITHUB_API_CACHE);
196-
const cached = await cache.match(request);
224+
const cached = await cache.match(request.url);
197225
if (cached) {
198226
console.log('Returning cached GitHub API response (offline)');
199227
return cached.clone();

0 commit comments

Comments
 (0)