Skip to content

Commit 3088ec9

Browse files
fix: service worker
1 parent 65df686 commit 3088ec9

1 file changed

Lines changed: 64 additions & 58 deletions

File tree

Lines changed: 64 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,69 @@
1-
self.addEventListener('install', (ev) => {
2-
// console.log('[service worker] installing');
3-
ev.waitUntil(self.skipWaiting());
1+
const CACHE_NAME = 'webgal-critical-assets-v3';
2+
const GAME_PREFIX = '/game/';
3+
const CRITICAL_PATHS = ['/game/background/', '/game/figure/', '/game/bgm/', '/game/vocal/', '/game/video/'];
4+
const LOG_PREFIX = '[WebGAL SW]';
5+
const loggedKeys = new Set();
6+
7+
function logOnce(key, ...args) {
8+
if (loggedKeys.has(key)) return;
9+
loggedKeys.add(key);
10+
console.log(LOG_PREFIX, ...args);
11+
}
12+
13+
self.addEventListener('install', (event) => {
14+
logOnce('install', `install ${CACHE_NAME}`);
15+
event.waitUntil(self.skipWaiting());
416
});
517

6-
// fetch事件是每次页面请求资源时触发的
7-
self.addEventListener('fetch', function (event) {
8-
const url = event.request.url;
9-
const isReturnCache = !!(url.match('/assets/') && !url.match('game'));
10-
if (isReturnCache) {
11-
// console.log('%cCACHED: ' + url, 'color: #005CAF; padding: 2px;');
18+
self.addEventListener('activate', (event) => {
19+
logOnce('activate', `activate ${CACHE_NAME}`);
20+
event.waitUntil(
21+
(async () => {
22+
const keys = await caches.keys();
23+
await Promise.all(keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key)));
24+
await self.clients.claim();
25+
})(),
26+
);
27+
});
28+
29+
function isCriticalGameRequest(request) {
30+
if (request.method !== 'GET') return false;
31+
const url = new URL(request.url);
32+
if (url.origin !== self.location.origin) return false;
33+
if (!url.pathname.startsWith(GAME_PREFIX)) return false;
34+
return CRITICAL_PATHS.some((prefix) => url.pathname.startsWith(prefix));
35+
}
36+
37+
async function cacheFirst(request) {
38+
const cache = await caches.open(CACHE_NAME);
39+
const cached = await cache.match(request.url);
40+
if (cached) {
41+
logOnce(`hit:${request.url}`, 'cache hit:', new URL(request.url).pathname);
42+
return cached;
1243
}
13-
if (!isReturnCache) {
14-
event.respondWith(fetch(event.request));
15-
} else {
16-
event.respondWith(
17-
// 检查在缓存中是否有匹配的资源
18-
caches.match(event.request).then(function (response) {
19-
// 如果缓存中有匹配的资源,则返回缓存资源
20-
if (response) {
21-
return response;
22-
}
23-
// 如果没有匹配的资源,则尝试从网络请求
24-
// 同时将获取的资源存入缓存
25-
return fetch(event.request)
26-
.then(function (networkResponse) {
27-
console.log('%cCACHED: ' + url, 'color: #005CAF; padding: 2px;');
28-
if (networkResponse.status === 206 && event.request.headers.has('range')) {
29-
// 如果是部分响应且请求带有Range头,则创建新的请求,将完整响应返回给客户端
30-
// eslint-disable-next-line max-nested-callbacks
31-
return fetch(event.request.url).then(function (fullNetworkResponse) {
32-
const headers = {};
33-
for (let entry of fullNetworkResponse.headers.entries()) {
34-
headers[entry[0]] = entry[1];
35-
}
36-
const fullResponse = new Response(fullNetworkResponse.body, {
37-
status: fullNetworkResponse.status,
38-
statusText: fullNetworkResponse.statusText,
39-
headers: headers,
40-
});
41-
const clonedResponse = fullResponse.clone();
42-
// eslint-disable-next-line max-nested-callbacks
43-
caches.open('my-cache').then(function (cache) {
44-
cache.put(event.request, clonedResponse);
45-
});
46-
return fullResponse;
47-
});
48-
}
49-
const clonedResponse = networkResponse.clone();
50-
// eslint-disable-next-line max-nested-callbacks
51-
caches.open('my-cache').then(function (cache) {
52-
cache.put(event.request, clonedResponse);
53-
});
54-
return networkResponse;
55-
})
56-
.catch(function (error) {
57-
console.error('Fetching failed:', error);
58-
throw error;
59-
});
60-
}),
61-
);
44+
45+
const response = await fetch(request);
46+
if (response.ok && response.status === 200) {
47+
await cache.put(request.url, response.clone());
48+
logOnce(`cache:${request.url}`, 'cached:', new URL(request.url).pathname);
6249
}
50+
return response;
51+
}
52+
53+
self.addEventListener('fetch', (event) => {
54+
const { request } = event;
55+
if (!isCriticalGameRequest(request)) return;
56+
57+
// Audio/video range requests are passed through to avoid partial-content edge cases.
58+
if (request.headers.has('range')) {
59+
logOnce(`range:${request.url}`, 'range passthrough:', new URL(request.url).pathname);
60+
event.respondWith(fetch(request));
61+
return;
62+
}
63+
64+
event.respondWith(
65+
cacheFirst(request).catch(() => {
66+
return fetch(request);
67+
}),
68+
);
6369
});

0 commit comments

Comments
 (0)