Skip to content
This repository was archived by the owner on Feb 23, 2026. It is now read-only.

Commit f912f36

Browse files
committed
Fix: リクエストの失敗や、デバイスが何かしらの原因でオフラインになった際に真っ白なページでスタックする問題を修正
1 parent 9558993 commit f912f36

1 file changed

Lines changed: 44 additions & 13 deletions

File tree

packages/sw/src/sw.ts

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,21 @@ globalThis.addEventListener('activate', ev => {
2929
});
3030

3131
async function offlineContentHTML() {
32-
const i18n = await (swLang.i18n ?? swLang.fetchLocale()) as Partial<I18n<Locale>>;
32+
const controller = new AbortController();
33+
const timeout = globalThis.setTimeout(() => {
34+
controller.abort('i18n-timeout');
35+
}, 3000);
36+
37+
let i18n: Partial<I18n<Locale>>;
38+
39+
try {
40+
i18n = await (swLang.i18n ?? swLang.fetchLocale()) as Partial<I18n<Locale>>;
41+
} catch {
42+
i18n = {};
43+
} finally {
44+
globalThis.clearTimeout(timeout);
45+
}
46+
3347
const messages = {
3448
title: i18n.ts?._offlineScreen.title ?? 'Offline - Could not connect to server',
3549
header: i18n.ts?._offlineScreen.header ?? 'Could not connect to server',
@@ -50,20 +64,37 @@ globalThis.addEventListener('fetch', ev => {
5064
}
5165

5266
if (!isHTMLRequest) return;
53-
ev.respondWith(
54-
fetch(ev.request)
55-
.catch(async () => {
56-
const html = await offlineContentHTML();
57-
return new Response(html, {
58-
status: 200,
59-
headers: {
60-
'content-type': 'text/html',
61-
},
62-
});
63-
}),
64-
);
67+
ev.respondWith(respondToNavigation(ev.request));
6568
});
6669

70+
async function respondToNavigation(request: Request): Promise<Response> {
71+
const controller = new AbortController();
72+
const timeout = globalThis.setTimeout(() => {
73+
controller.abort('navigation-timeout');
74+
}, 5000);
75+
76+
try {
77+
const response = await fetch(request, { signal: controller.signal });
78+
79+
if (response?.status && response.status < 400) return response;
80+
if (response?.type === 'opaqueredirect') return response;
81+
} catch (error) {
82+
if (_DEV_) {
83+
console.warn('navigation fetch failed; showing offline page', error);
84+
}
85+
} finally {
86+
globalThis.clearTimeout(timeout);
87+
}
88+
89+
const html = await offlineContentHTML();
90+
return new Response(html, {
91+
status: 200,
92+
headers: {
93+
'content-type': 'text/html',
94+
},
95+
});
96+
}
97+
6798
globalThis.addEventListener('push', ev => {
6899
// クライアント取得
69100
ev.waitUntil(globalThis.clients.matchAll({

0 commit comments

Comments
 (0)