// Service Worker для NoteJS const APP_VERSION = '1.0.2'; const CACHE_NAME = `notejs-v${APP_VERSION}`; const STATIC_CACHE_NAME = `notejs-static-v${APP_VERSION}`; // Файлы для кэширования при установке const STATIC_FILES = [ '/', '/index.html', '/style.css', '/manifest.json', '/icons/icon-192x192.png', '/icons/icon-512x512.png' ]; // Установка Service Worker self.addEventListener('install', (event) => { console.log('[SW] Установка Service Worker'); event.waitUntil( caches.open(STATIC_CACHE_NAME) .then((cache) => { console.log('[SW] Кэширование статических файлов'); return cache.addAll(STATIC_FILES); }) .then(() => { console.log('[SW] Статические файлы закэшированы'); return self.skipWaiting(); }) .catch((error) => { console.error('[SW] Ошибка при кэшировании статических файлов:', error); // Продолжаем работу даже если кэширование не удалось return self.skipWaiting(); }) ); }); // Активация Service Worker self.addEventListener('activate', (event) => { console.log('[SW] Активация Service Worker'); event.waitUntil( caches.keys() .then((cacheNames) => { return Promise.all( cacheNames.map((cacheName) => { // Удаляем старые кэши if (cacheName !== STATIC_CACHE_NAME) { console.log('[SW] Удаление старого кэша:', cacheName); return caches.delete(cacheName); } }) ); }) .then(() => { console.log('[SW] Service Worker активирован'); return self.clients.claim(); }) ); }); // Перехват запросов self.addEventListener('fetch', (event) => { const { request } = event; const url = new URL(request.url); // Пропускаем запросы к API и загрузкам if (url.pathname.startsWith('/api/') || url.pathname.startsWith('/uploads/') || url.pathname.startsWith('/database/')) { return; } // Обрабатываем только GET запросы if (request.method === 'GET') { event.respondWith( handleRequest(request) ); } }); async function handleRequest(request) { try { // Сначала пытаемся получить из кэша const cachedResponse = await caches.match(request); if (cachedResponse) { console.log('[SW] Запрос из кэша:', request.url); return cachedResponse; } // Если нет в кэше, загружаем из сети console.log('[SW] Запрос к сети:', request.url); const networkResponse = await fetch(request); // Кэшируем успешные ответы if (networkResponse.ok) { const cache = await caches.open(STATIC_CACHE_NAME); cache.put(request, networkResponse.clone()); } return networkResponse; } catch (error) { console.error('[SW] Ошибка при обработке запроса:', error); // Fallback для HTML страниц if (request.headers.get('accept')?.includes('text/html')) { const fallbackResponse = await caches.match('/index.html'); if (fallbackResponse) { return fallbackResponse; } } throw error; } } // Обработка сообщений от основного потока self.addEventListener('message', (event) => { console.log('[SW] Получено сообщение:', event.data); if (event.data && event.data.type === 'SKIP_WAITING') { self.skipWaiting(); } if (event.data && event.data.type === 'GET_VERSION') { event.ports[0].postMessage({ version: CACHE_NAME }); } if (event.data && event.data.type === 'FORCE_UPDATE_CACHE') { forceUpdateCache(); } if (event.data && event.data.type === 'CLEAR_ALL_CACHE') { clearAllCache(); } }); // Функция принудительного обновления кэша async function forceUpdateCache() { console.log('[SW] Принудительное обновление кэша...'); try { // Удаляем все старые кэши const cacheNames = await caches.keys(); await Promise.all( cacheNames.map(cacheName => { console.log('[SW] Удаление кэша:', cacheName); return caches.delete(cacheName); }) ); // Создаем новый кэш с актуальной версией const newCache = await caches.open(STATIC_CACHE_NAME); await newCache.addAll(STATIC_FILES); console.log('[SW] Кэш успешно обновлен до версии:', APP_VERSION); // Уведомляем клиентов об обновлении const clients = await self.clients.matchAll(); clients.forEach(client => { client.postMessage({ type: 'CACHE_UPDATED', version: APP_VERSION }); }); } catch (error) { console.error('[SW] Ошибка при обновлении кэша:', error); } } // Функция полной очистки кэша async function clearAllCache() { console.log('[SW] Полная очистка кэша...'); try { const cacheNames = await caches.keys(); await Promise.all( cacheNames.map(cacheName => { console.log('[SW] Удаление кэша:', cacheName); return caches.delete(cacheName); }) ); console.log('[SW] Весь кэш очищен'); // Уведомляем клиентов об очистке const clients = await self.clients.matchAll(); clients.forEach(client => { client.postMessage({ type: 'CACHE_CLEARED' }); }); } catch (error) { console.error('[SW] Ошибка при очистке кэша:', error); } }