// Service Worker for 宇之然内容创作平台 const CACHE_NAME = 'yuzhiran-v3'; const CACHE_URLS = [ '/index.html', '/offline.html', '/manifest.json' ]; // 安装事件:预缓存核心资源 self.addEventListener('install', (event) => { console.log('[SW] Installing...'); event.waitUntil( caches.open(CACHE_NAME).then((cache) => { console.log('[SW] Pre-caching core assets'); return cache.addAll(CACHE_URLS.map(url => { return new Promise((resolve, reject) => { fetch(url).then(response => { if (response.ok) { resolve(url); } else { reject(new Error(`Failed to fetch ${url}: ${response.status}`)); } }).catch(() => { resolve(url); }); }); })); }).catch(err => { console.error('[SW] Install failed:', err); }) ); self.skipWaiting(); }); // 激活事件:清理旧缓存 self.addEventListener('activate', (event) => { console.log('[SW] Activating...'); event.waitUntil( caches.keys().then((cacheNames) => { return Promise.all( cacheNames.map((cache) => { if (cache !== CACHE_NAME) { console.log('[SW] Deleting old cache:', cache); return caches.delete(cache); } }) ); }) ); self.clients.claim(); }); // 网络请求拦截 self.addEventListener('fetch', (event) => { const { request } = event; const url = new URL(request.url); // 只处理同源请求 if (url.origin !== location.origin) { return; } // API 请求:Network Only if (url.pathname.startsWith('/api/')) { event.respondWith(fetch(request)); return; } // HTML 文档:Network First(确保 landing page 始终加载最新版) if (url.pathname === '/' || url.pathname.endsWith('.html')) { event.respondWith( fetch(request) .then(response => { if (response.ok) { const clone = response.clone(); caches.open(CACHE_NAME).then(cache => cache.put(request, clone)); } return response; }) .catch(() => { return caches.match(request).then(cached => { return cached || caches.match('/offline.html'); }); }) ); return; } // 其他静态资源:Cache First event.respondWith( caches.match(request).then((cached) => { if (cached) { fetch(request).then(response => { if (response.ok) { caches.open(CACHE_NAME).then(cache => cache.put(request, response)); } }); return cached; } return fetch(request).then(response => { if (response.ok && response.status === 200) { const clone = response.clone(); caches.open(CACHE_NAME).then(cache => cache.put(request, clone)); } return response; }).catch(() => { if (request.destination === 'document') { return caches.match('/offline.html'); } }); }) ); }); // 后台同步 self.addEventListener('sync', (event) => { if (event.tag === 'sync-logs') { event.waitUntil(syncLogs()); } }); async function syncLogs() { console.log('[SW] Syncing logs...'); }