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/' ] ;
1+ const CACHE_PREFIX = 'webgal-' ;
2+ const CACHE_NAME = 'webgal-build-assets-v1' ;
43const LOG_PREFIX = '[WebGAL SW]' ;
4+ const HASHED_BUILD_ASSET_RE = / ( ^ | \/ ) a s s e t s \/ [ ^ / ? # ] + - [ A - Z a - z 0 - 9 _ - ] { 8 , } \. (?: j s | c s s | t t f | w o f f | w o f f 2 ) $ / ;
55const loggedKeys = new Set ( ) ;
66
77function logOnce ( key , ...args ) {
@@ -20,66 +20,41 @@ self.addEventListener('activate', (event) => {
2020 event . waitUntil (
2121 ( async ( ) => {
2222 const keys = await caches . keys ( ) ;
23- await Promise . all ( keys . filter ( ( key ) => key !== CACHE_NAME ) . map ( ( key ) => caches . delete ( key ) ) ) ;
23+ await Promise . all ( keys . filter ( ( key ) => key . startsWith ( CACHE_PREFIX ) && key !== CACHE_NAME ) . map ( ( key ) => caches . delete ( key ) ) ) ;
2424 await self . clients . claim ( ) ;
2525 } ) ( ) ,
2626 ) ;
2727} ) ;
2828
29- function isCriticalGameRequest ( request ) {
29+ function isHashedBuildAssetRequest ( request ) {
3030 if ( request . method !== 'GET' ) return false ;
3131 const url = new URL ( request . url ) ;
3232 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 ) ) ;
33+ return HASHED_BUILD_ASSET_RE . test ( url . pathname ) ;
3534}
3635
37- // Stale-while-revalidate: return cached response immediately, then update cache in background.
38- async function staleWhileRevalidate ( request ) {
36+ async function cacheFirst ( request ) {
3937 const cache = await caches . open ( CACHE_NAME ) ;
40- const cached = await cache . match ( request . url ) ;
41-
42- const fetchAndUpdate = async ( ) => {
43- try {
44- const response = await fetch ( request ) ;
45- if ( response . ok ) {
46- await cache . put ( request . url , response . clone ( ) ) ;
47- }
48- return response ;
49- } catch ( e ) {
50- return null ;
51- }
52- } ;
53-
38+ const cached = await cache . match ( request ) ;
5439 if ( cached ) {
55- logOnce ( `hit:${ request . url } ` , 'cache hit (revalidating):' , new URL ( request . url ) . pathname ) ;
56- // Revalidate in background — don't await
57- fetchAndUpdate ( ) ;
40+ logOnce ( `hit:${ request . url } ` , 'cache hit:' , new URL ( request . url ) . pathname ) ;
5841 return cached ;
5942 }
6043
61- // No cache — must wait for network
6244 const response = await fetch ( request ) ;
63- if ( response . ok ) {
64- await cache . put ( request . url , response . clone ( ) ) ;
45+ if ( response . ok && response . status === 200 ) {
46+ await cache . put ( request , response . clone ( ) ) ;
6547 logOnce ( `cache:${ request . url } ` , 'cached:' , new URL ( request . url ) . pathname ) ;
6648 }
6749 return response ;
6850}
6951
7052self . addEventListener ( 'fetch' , ( event ) => {
7153 const { request } = event ;
72- if ( ! isCriticalGameRequest ( request ) ) return ;
73-
74- // Audio/video range requests are passed through to avoid partial-content edge cases.
75- if ( request . headers . has ( 'range' ) ) {
76- logOnce ( `range:${ request . url } ` , 'range passthrough:' , new URL ( request . url ) . pathname ) ;
77- event . respondWith ( fetch ( request ) ) ;
78- return ;
79- }
54+ if ( ! isHashedBuildAssetRequest ( request ) ) return ;
8055
8156 event . respondWith (
82- staleWhileRevalidate ( request ) . catch ( ( ) => {
57+ cacheFirst ( request ) . catch ( ( ) => {
8358 return fetch ( request ) ;
8459 } ) ,
8560 ) ;
0 commit comments