@@ -52,6 +52,24 @@ self.addEventListener('activate', event => {
5252 ) ;
5353} ) ;
5454
55+ // Helper function to identify large game files
56+ function isLargeGameFile ( url ) {
57+ // Add patterns for your large game files
58+ const gameFilePatterns = [
59+ / \. d a t a $ / , // Unity WebGL data files
60+ / \. w a s m $ / , // WebAssembly files
61+ / \. b u n d l e $ / , // Asset bundles
62+ / \. u n i t y 3 d $ / , // Unity asset files
63+ / \. p a k $ / , // Package files
64+ / \. b i n $ / , // Binary files
65+ // Add your specific large file extensions here
66+ ] ;
67+
68+ return gameFilePatterns . some ( pattern => pattern . test ( url . pathname ) ) ||
69+ url . pathname . includes ( 'assets/' ) ||
70+ url . pathname . includes ( 'gamedata/' ) ;
71+ }
72+
5573// Helper function to determine if a request should be cached
5674function isCacheableRequest ( request ) {
5775 const url = new URL ( request . url ) ;
@@ -84,7 +102,9 @@ function isCacheableRequest(request) {
84102 '.png' , '.jpg' , '.jpeg' , '.gif' , '.webp' , '.svg' ,
85103 '.woff' , '.woff2' , '.ttf' , '.otf' ,
86104 '.mp3' , '.ogg' , '.wav' ,
87- '.mp4' , '.webm'
105+ '.mp4' , '.webm' ,
106+ // Game file extensions
107+ '.data' , '.wasm' , '.bundle' , '.unity3d' , '.pak' , '.bin'
88108 ] ;
89109
90110 if ( extensions . some ( ext => url . pathname . endsWith ( ext ) ) ) {
@@ -94,6 +114,15 @@ function isCacheableRequest(request) {
94114 return false ;
95115}
96116
117+ // Helper function to check if response is valid for caching
118+ function isValidResponse ( response ) {
119+ return response &&
120+ response . ok &&
121+ response . status >= 200 &&
122+ response . status < 300 &&
123+ response . status !== 209 ; // Explicitly exclude 209 responses
124+ }
125+
97126// Network-first strategy with fallback to cache
98127async function networkFirstStrategy ( request ) {
99128 try {
@@ -109,15 +138,25 @@ async function networkFirstStrategy(request) {
109138 // Try network first
110139 const networkResponse = await fetch ( request , fetchOptions ) ;
111140
112- // If successful, clone and cache
113- if ( networkResponse . ok ) {
141+ // If successful and valid for caching , clone and cache
142+ if ( isValidResponse ( networkResponse ) ) {
114143 const cache = await caches . open ( CACHE_NAME ) ;
115144 cache . put ( request , networkResponse . clone ( ) ) ;
116145 return networkResponse ;
117146 }
118147
119- // If network fails with an error status, try cache
120- throw new Error ( 'Network response was not ok' ) ;
148+ // If network response is not valid for caching, try cache
149+ if ( networkResponse . status === 209 ) {
150+ console . log ( 'Received 209 response, falling back to cache for:' , request . url ) ;
151+ }
152+
153+ const cachedResponse = await caches . match ( request ) ;
154+ if ( cachedResponse ) {
155+ return cachedResponse ;
156+ }
157+
158+ // Return the network response even if not cacheable
159+ return networkResponse ;
121160 } catch ( error ) {
122161 // Fall back to cache
123162 const cachedResponse = await caches . match ( request ) ;
@@ -154,8 +193,8 @@ async function cacheFirstStrategy(request) {
154193
155194 const networkResponse = await fetch ( request , fetchOptions ) ;
156195
157- // Cache the network response for future
158- if ( networkResponse . ok ) {
196+ // Cache the network response for future if it's valid
197+ if ( isValidResponse ( networkResponse ) ) {
159198 const cache = await caches . open ( CACHE_NAME ) ;
160199 cache . put ( request , networkResponse . clone ( ) ) ;
161200 }
@@ -181,7 +220,7 @@ async function staleWhileRevalidateStrategy(request) {
181220 }
182221
183222 const fetchPromise = fetch ( request , fetchOptions ) . then ( networkResponse => {
184- if ( networkResponse . ok ) {
223+ if ( isValidResponse ( networkResponse ) ) {
185224 const cache = caches . open ( CACHE_NAME ) . then ( cache => {
186225 cache . put ( request , networkResponse . clone ( ) ) ;
187226 return networkResponse ;
@@ -207,7 +246,8 @@ async function timeAwareCacheFirstStrategy(request) {
207246 if ( cachedResponse && ! isStale ) {
208247 return cachedResponse ;
209248 }
210- console . log ( request . url , isStale )
249+
250+ console . log ( 'Cache miss or stale for:' , request . url , { isStale, hasCached : ! ! cachedResponse } ) ;
211251
212252 // Otherwise, get from network (either no cache or stale cache)
213253 try {
@@ -219,17 +259,20 @@ async function timeAwareCacheFirstStrategy(request) {
219259
220260 const networkResponse = await fetch ( request , fetchOptions ) ;
221261
222- // Cache the network response for future
223- if ( networkResponse . ok ) {
262+ // Cache the network response for future if it's valid
263+ if ( isValidResponse ( networkResponse ) ) {
224264 const cache = await caches . open ( CACHE_NAME ) ;
225265 await cache . put ( request , networkResponse . clone ( ) ) ;
226266 await updateCacheTimestamp ( request . url ) ;
267+ } else if ( networkResponse . status === 209 ) {
268+ console . log ( 'Received 209 response, not caching:' , request . url ) ;
227269 }
228270
229271 return networkResponse ;
230272 } catch ( error ) {
231273 // If network fails and we have a cached version (even if stale), return it
232274 if ( cachedResponse ) {
275+ console . log ( 'Network failed, returning stale cache for:' , request . url ) ;
233276 return cachedResponse ;
234277 }
235278
@@ -249,35 +292,49 @@ async function saveMetadataStore(metadata) {
249292
250293// Helper function to update timestamp for a cached file
251294async function updateCacheTimestamp ( url ) {
252- const metadata = await getMetadataStore ( ) ;
253- metadata [ url ] = Date . now ( ) ;
254- await saveMetadataStore ( metadata ) ;
295+ try {
296+ const metadata = await getMetadataStore ( ) ;
297+ metadata [ url ] = Date . now ( ) ;
298+ await saveMetadataStore ( metadata ) ;
299+ } catch ( error ) {
300+ console . error ( 'Failed to update cache timestamp:' , error ) ;
301+ }
255302}
256303
257304async function isFileStale ( url ) {
258- const metadata = await getMetadataStore ( ) ;
259- const timestamp = metadata [ url ] ;
260-
261- if ( ! timestamp ) {
262- console . log ( "No timestamp for" , url ) ;
263- return true ; // No timestamp means we should revalidate
305+ try {
306+ const metadata = await getMetadataStore ( ) ;
307+ const timestamp = metadata [ url ] ;
308+
309+ if ( ! timestamp ) {
310+ console . log ( "No timestamp for" , url ) ;
311+ return true ; // No timestamp means we should revalidate
312+ }
313+
314+ const now = Date . now ( ) ;
315+ const age = now - timestamp ;
316+ const maxAgeMs = MAX_AGE_DAYS * 24 * 60 * 60 * 1000 ; // Convert days to milliseconds
317+ return age > maxAgeMs ;
318+ } catch ( error ) {
319+ console . error ( 'Error checking if file is stale:' , error ) ;
320+ return true ; // Assume stale on error
264321 }
265-
266- const now = Date . now ( ) ;
267- const age = now - timestamp ;
268- const maxAgeMs = MAX_AGE_DAYS * 24 * 60 * 60 * 1000 ; // Convert days to milliseconds
269- return age > maxAgeMs ;
270322}
271323
272324// Helper function to get the cache metadata store
273325async function getMetadataStore ( ) {
274- const cache = await caches . open ( CACHE_NAME ) ;
275- const metadataResponse = await cache . match ( CACHE_METADATA_KEY ) ;
276-
277- if ( metadataResponse ) {
278- return metadataResponse . json ( ) ;
279- } else {
280- // Initialize with empty metadata if none exists
326+ try {
327+ const cache = await caches . open ( CACHE_NAME ) ;
328+ const metadataResponse = await cache . match ( CACHE_METADATA_KEY ) ;
329+
330+ if ( metadataResponse ) {
331+ return await metadataResponse . json ( ) ;
332+ } else {
333+ // Initialize with empty metadata if none exists
334+ return { } ;
335+ }
336+ } catch ( error ) {
337+ console . error ( 'Error getting metadata store:' , error ) ;
281338 return { } ;
282339 }
283340}
@@ -299,11 +356,12 @@ self.addEventListener('fetch', event => {
299356 if ( isImage && isExternalDomain ) {
300357 event . respondWith ( timeAwareCacheFirstStrategy ( request ) ) ;
301358 }
302- // For game assets, use cache-first
303- else if ( request . url . includes ( 'game_' ) ) {
359+ // For game assets, use cache-first (these are your large files)
360+ else if ( request . url . includes ( 'game_' ) || isLargeGameFile ( url ) ) {
361+ console . log ( 'Service worker caching game asset:' , request . url ) ;
304362 event . respondWith ( cacheFirstStrategy ( request ) ) ;
305363 }
306- // For HTML and JSON files, use network-first to get latest versions
364+ // For HTML, JSON, TXT and JS files, use network-first to get latest versions
307365 else if ( request . url . endsWith ( '.html' ) || request . url . endsWith ( '.json' ) || request . url . endsWith ( '.txt' ) || request . url . endsWith ( '.js' ) ) {
308366 event . respondWith ( networkFirstStrategy ( request ) ) ;
309367 }
@@ -323,4 +381,14 @@ self.addEventListener('message', event => {
323381 event . ports [ 0 ] . postMessage ( { status : 'Cache cleared' } ) ;
324382 } ) ;
325383 }
384+
385+ // Handle force refresh for specific URLs
386+ if ( event . data && event . data . action === 'FORCE_REFRESH' ) {
387+ const url = event . data . url ;
388+ caches . open ( CACHE_NAME ) . then ( cache => {
389+ cache . delete ( url ) . then ( ( ) => {
390+ event . ports [ 0 ] . postMessage ( { status : `Cache cleared for ${ url } ` } ) ;
391+ } ) ;
392+ } ) ;
393+ }
326394} ) ;
0 commit comments