NoteJS/public/sw.js
Fovway fbc2b5259c Добавлены функции управления кэшем и обновления PWA
- Реализованы функции для принудительного обновления кэша и полной очистки кэша в классе PWAManager.
- Добавлены обработчики сообщений от сервисного работника для обновления кэша и очистки кэша.
- Обновлен сервисный работник для поддержки новых функций управления кэшем и уведомлений о статусе кэша.
- Добавлены глобальные функции для управления кэшем через интерфейс браузера.
2025-10-20 09:27:55 +07:00

200 lines
6.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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);
}
}