This commit is contained in:
@@ -1,25 +1,155 @@
|
||||
// const VER = 14
|
||||
// const VER = 18
|
||||
|
||||
self.addEventListener('message', async (event) => {
|
||||
event.waitUntil(debug(Object.assign({ answer: true }, event.data)))
|
||||
})
|
||||
const CACHE_NAME = 'cache-v1'
|
||||
const TEMP_PAGE_URL = '/offline.html'
|
||||
const STATIC_ASSETS = [TEMP_PAGE_URL, '/css/offline.css']
|
||||
|
||||
self.addEventListener('install', (event) => {
|
||||
// The promise that skipWaiting() returns can be safely ignored.
|
||||
event.waitUntil(self.skipWaiting().then(() => debug({ installed: true })))
|
||||
|
||||
// Perform any other actions required for your
|
||||
// service worker to install, potentially inside
|
||||
// of event.waitUntil();
|
||||
event.waitUntil(caches.open(CACHE_NAME).then((cache) => cache.addAll(STATIC_ASSETS)))
|
||||
})
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
event.waitUntil(
|
||||
// Привязка нового сервис-воркера к текущим клиентам
|
||||
clients.claim().then(() => debug(event.source, { activated: true })),
|
||||
caches.keys().then((cacheNames) =>
|
||||
Promise.all(
|
||||
cacheNames.map((cache) => {
|
||||
if (cache !== CACHE_NAME) {
|
||||
return caches.delete(cache)
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
self.addEventListener('fetch', (event) => {
|
||||
const url = new URL(event.request.url)
|
||||
|
||||
// Обрабатываем только HTTP/HTTPS запросы
|
||||
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
||||
return
|
||||
}
|
||||
|
||||
if (event.request.mode === 'navigate') {
|
||||
// Для навигационных запросов сначала отдаём `/offline.html`, пока основная страница загружается
|
||||
event.respondWith(handleNavigationRequest(event.request))
|
||||
} else if (STATIC_ASSETS.includes(url.pathname)) {
|
||||
// Кэшируем только offline.html и его CSS
|
||||
event.respondWith(caches.match(event.request))
|
||||
}
|
||||
})
|
||||
|
||||
const TEMP_CACHE = new Map() // Используем карту для временного хранения
|
||||
|
||||
async function handleNavigationRequest(request) {
|
||||
if (TEMP_CACHE.has(request.url) && navigator.onLine) {
|
||||
return TEMP_CACHE.get(request.url).clone()
|
||||
}
|
||||
|
||||
const cache = await caches.open(CACHE_NAME)
|
||||
|
||||
// Отдаём временную страницу из кеша
|
||||
const tempResponse = await cache.match(TEMP_PAGE_URL)
|
||||
|
||||
// Попытка загрузить основную страницу в фоновом режиме
|
||||
fetch(request)
|
||||
.then(async (networkResponse) => {
|
||||
if (networkResponse && networkResponse.ok) {
|
||||
// Сохраняем клон в TEMP_CACHE
|
||||
TEMP_CACHE.set(request.url, networkResponse)
|
||||
|
||||
// Сообщаем клиенту, что основная страница готова
|
||||
const allClients = await clients.matchAll({ type: 'window' })
|
||||
allClients.forEach((client) =>
|
||||
client.postMessage({
|
||||
type: 'MAIN_PAGE_READY',
|
||||
}),
|
||||
)
|
||||
|
||||
// Удаляем из TEMP_CACHE через минимальное время
|
||||
setTimeout(() => {
|
||||
TEMP_CACHE.delete(request.url)
|
||||
}, 5000)
|
||||
} else {
|
||||
throw new Error('Failed to fetch main page')
|
||||
}
|
||||
})
|
||||
.catch(async (error) => {
|
||||
console.error('Error loading main page:', error)
|
||||
|
||||
// Сообщаем клиенту об ошибке сети
|
||||
const allClients = await clients.matchAll({ type: 'window' })
|
||||
allClients.forEach((client) =>
|
||||
client.postMessage({
|
||||
type: 'NETWORK_ERROR',
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
// Возвращаем временную страницу
|
||||
return tempResponse
|
||||
}
|
||||
|
||||
async function updateStaticAssetsCache() {
|
||||
const cache = await caches.open(CACHE_NAME)
|
||||
|
||||
// Обновляем ресурсы
|
||||
try {
|
||||
await Promise.all(
|
||||
STATIC_ASSETS.map(async (asset) => {
|
||||
const response = await fetch(asset, { cache: 'no-store' })
|
||||
if (response.ok) {
|
||||
await cache.put(asset, response.clone())
|
||||
} else {
|
||||
console.error(`Failed to fetch ${asset}:`, response.status)
|
||||
}
|
||||
}),
|
||||
)
|
||||
console.log('STATIC_ASSETS обновлены.')
|
||||
} catch (error) {
|
||||
console.error('Ошибка обновления STATIC_ASSETS:', error)
|
||||
}
|
||||
}
|
||||
|
||||
self.addEventListener('message', async (event) => {
|
||||
if (event.data && event.data.type === 'SKIP_WAITING') {
|
||||
self.skipWaiting()
|
||||
} else if (event.data && event.data.type === 'CHECK_ONLINE_STATUS') {
|
||||
const isOnline = navigator.onLine // Проверяем состояние сети
|
||||
event.ports[0].postMessage({ online: isOnline }) // Отправляем результат обратно
|
||||
} else if (event.data && event.data.type === 'UPDATE_STATIC_ASSETS') {
|
||||
event.waitUntil(updateStaticAssetsCache())
|
||||
} else {
|
||||
event.waitUntil(debug(Object.assign({ answer: true }, event.data)))
|
||||
}
|
||||
})
|
||||
|
||||
self.addEventListener('install', (event) => {
|
||||
event.waitUntil(
|
||||
caches.open(CACHE_NAME).then((cache) => {
|
||||
return cache.addAll(STATIC_ASSETS)
|
||||
}),
|
||||
)
|
||||
|
||||
self.skipWaiting().then(() => debug({ installed: true }))
|
||||
})
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
event.waitUntil(
|
||||
caches.keys().then((cacheNames) =>
|
||||
Promise.all(
|
||||
cacheNames.map((cache) => {
|
||||
if (cache !== CACHE_NAME) {
|
||||
return caches.delete(cache)
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
clients.claim().then(() => debug(event.source, { activated: true }))
|
||||
})
|
||||
|
||||
self.addEventListener('push', async (event) => {
|
||||
debug({
|
||||
event: 'push',
|
||||
|
||||
Reference in New Issue
Block a user