Android(TWA) 앱 패키징 + 재실행 불가 버그 수정
Cloudflare Pages 가 /index.html 을 / 로 308 리다이렉트하는데, 서비스워커가 그 리다이렉트 응답을 캐시해 두면 navigation 요청에 응답할 수 없어(스펙상 금지) 두 번째 실행부터 ERR_FAILED 로 앱이 아예 열리지 않았다. - sw.js: navigation 은 네트워크 우선 + 캐시된 './' 오프라인 폴백, 프리캐시는 리다이렉트 플래그 없는 새 Response 로 복사해 저장 (tetrig-v2) - manifest.webmanifest: start_url 을 './' 로 바꿔 리다이렉트 자체를 회피 - android/: Bubblewrap TWA 프로젝트 (kr.tkrmagid.tetrig, launchUrl '/') - .well-known/assetlinks.json: 서명 키 SHA-256 등록 → 주소창 없는 전체화면 실행
This commit is contained in:
32
sw.js
32
sw.js
@@ -1,16 +1,27 @@
|
||||
// TETRIG 서비스 워커 — 오프라인 캐시 (앱처럼 설치/실행)
|
||||
const CACHE = 'tetrig-v1';
|
||||
const CACHE = 'tetrig-v2';
|
||||
const ASSETS = [
|
||||
'./',
|
||||
'./index.html',
|
||||
'./manifest.webmanifest',
|
||||
'./icon-192.png',
|
||||
'./icon-512.png',
|
||||
'./apple-touch-icon.png',
|
||||
];
|
||||
|
||||
// Cloudflare Pages 는 /index.html 을 / 로 308 리다이렉트한다.
|
||||
// 리다이렉트된 Response 를 그대로 캐시하면 navigation 요청에 응답할 수 없어
|
||||
// (spec 상 금지) 두 번째 실행부터 ERR_FAILED 가 난다. 새 Response 로 복사해 저장한다.
|
||||
async function cacheClean(cache, url) {
|
||||
const res = await fetch(url, { cache: 'reload' });
|
||||
if (!res.ok) return;
|
||||
const body = await res.blob();
|
||||
await cache.put(url, new Response(body, { status: 200, statusText: 'OK', headers: res.headers }));
|
||||
}
|
||||
|
||||
self.addEventListener('install', (e) => {
|
||||
e.waitUntil(caches.open(CACHE).then((c) => c.addAll(ASSETS)));
|
||||
e.waitUntil(
|
||||
caches.open(CACHE).then((c) => Promise.all(ASSETS.map((u) => cacheClean(c, u))))
|
||||
);
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
@@ -23,10 +34,17 @@ self.addEventListener('activate', (e) => {
|
||||
self.clients.claim();
|
||||
});
|
||||
|
||||
// 캐시 우선, 없으면 네트워크 (게임은 정적이라 오프라인 완전 동작)
|
||||
self.addEventListener('fetch', (e) => {
|
||||
if (e.request.method !== 'GET') return;
|
||||
e.respondWith(
|
||||
caches.match(e.request).then((r) => r || fetch(e.request))
|
||||
);
|
||||
|
||||
// 페이지 진입: 네트워크 우선, 실패하면 캐시된 시작 문서로 오프라인 동작
|
||||
if (e.request.mode === 'navigate') {
|
||||
e.respondWith(
|
||||
fetch(e.request).catch(async () => (await caches.match('./')) || Response.error())
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// 나머지 정적 에셋: 캐시 우선
|
||||
e.respondWith(caches.match(e.request).then((r) => r || fetch(e.request)));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user