sw.js (4.2 KB)


  1 const CACHE_NAME = 'web-workshop-v1.2';
  2 const urlsToCache = [
  3   '/web_workshop/',
  4   '/web_workshop/index.html',
  5   '/web_workshop/manifest.json',
  6   '/web_workshop/resources/resource-manifest.json',
  7   '/web_workshop/resources/css/styles.css',
  8   '/web_workshop/resources/js/main.js',
  9   '/web_workshop/resources/js/codemirror-bundle.js'
 10 ];
 11 
 12 // Function to discover and cache all files in directories
 13 async function cacheDirectoryFiles(cache, directories) {
 14   for (const dir of directories) {
 15     try {
 16       // Try to fetch directory listing
 17       const response = await fetch(dir);
 18       if (response.ok) {
 19         const html = await response.text();
 20         // Extract file links from directory listing
 21         const links = html.match(/href="([^"]*\.(png|jpg|jpeg|gif|svg|webp|html|css|js|json|txt|md))"/gi);
 22         if (links) {
 23           const files = links.map(link => {
 24             const match = link.match(/href="([^"]*)"/);
 25             return match ? dir + match[1] : null;
 26           }).filter(Boolean);
 27           
 28           // Cache each file
 29           for (const file of files) {
 30             try {
 31               await cache.add(file);
 32             } catch (e) {
 33               console.log(`Failed to cache ${file}:`, e);
 34             }
 35           }
 36         }
 37       }
 38     } catch (e) {
 39       console.log(`Failed to cache directory ${dir}:`, e);
 40     }
 41   }
 42 }
 43 
 44 // Function to cache all resources using the generated manifest
 45 async function cacheResources(cache) {
 46   try {
 47     const response = await fetch('/web_workshop/resources/resource-manifest.json');
 48     if (response.ok) {
 49       const manifest = await response.json();
 50       console.log(`Caching ${manifest.images.length} images and ${manifest.resources.length} resources from manifest`);
 51       
 52       // Cache images
 53       for (const imagePath of manifest.images) {
 54         try {
 55           await cache.add(imagePath);
 56           console.log(`Cached image: ${imagePath}`);
 57         } catch (e) {
 58           console.log(`Failed to cache image ${imagePath}:`, e);
 59         }
 60       }
 61       
 62       // Cache resources
 63       for (const resourcePath of manifest.resources) {
 64         try {
 65           await cache.add(resourcePath);
 66           console.log(`Cached resource: ${resourcePath}`);
 67         } catch (e) {
 68           console.log(`Failed to cache resource ${resourcePath}:`, e);
 69         }
 70       }
 71     } else {
 72       console.log('No resource manifest found, skipping resource caching');
 73     }
 74   } catch (e) {
 75     console.log('Failed to load resource manifest:', e);
 76   }
 77 }
 78 
 79 // Install service worker and cache resources
 80 self.addEventListener('install', event => {
 81   event.waitUntil(
 82     caches.open(CACHE_NAME)
 83       .then(async cache => {
 84         // Cache all core files
 85         await cache.addAll(urlsToCache);
 86 
 87         // Cache all resources programmatically
 88         await cacheResources(cache);
 89       })
 90       .then(() => self.skipWaiting())
 91   );
 92 });
 93 
 94 // Activate service worker and clean up old caches
 95 self.addEventListener('activate', event => {
 96   event.waitUntil(
 97     caches.keys().then(cacheNames => {
 98       return Promise.all(
 99         cacheNames.map(cacheName => {
100           if (cacheName !== CACHE_NAME) {
101             return caches.delete(cacheName);
102           }
103         })
104       );
105     }).then(() => self.clients.claim())
106   );
107 });
108 
109 // Fetch strategy: Network first, then cache (for updates when online)
110 self.addEventListener('fetch', event => {
111   event.respondWith(
112     fetch(event.request)
113       .then(response => {
114         // If we got a response, add it to the cache
115         if (response.status === 200) {
116           const responseClone = response.clone();
117           caches.open(CACHE_NAME)
118             .then(cache => cache.put(event.request, responseClone));
119         }
120         return response;
121       })
122       .catch(() => {
123         // Network failed, try cache
124         return caches.match(event.request)
125           .then(response => {
126             if (response) {
127               return response;
128             }
129             // If not in cache and it's a navigation request, serve index.html
130             if (event.request.mode === 'navigate') {
131               return caches.match('/index.html');
132             }
133             throw new Error('No cached version available');
134           });
135       })
136   );
137 });