Front-End/static/sw.js
2026-02-13 20:15:37 -03:00

267 lines
7.9 KiB
JavaScript

const CACHE_NAME = 'basspago-v1.0.0';
const urlsToCache = [
// Páginas principais
'/',
'/pix',
'/pdv',
'/conta-digital',
'/desenvolvedores',
'/precos',
// Favicons
'/favicon-16x16.png',
'/apple-touch-icon.png',
// Imagens críticas do hero/homepage
'/src/lib/assets/backgroundSection2.png',
'/src/lib/assets/phone-card.png',
'/src/lib/assets/backgroundPDV.png',
'/src/lib/assets/phone-qrcode.png',
// Logos de parceiros (críticos para hero)
'/src/lib/assets/marca-cambionet.png',
'/src/lib/assets/marca-cazco.png',
'/src/lib/assets/marca-cdl.png',
'/src/lib/assets/marca-fecomercio-rs.png',
'/src/lib/assets/marca-gramado-sumit.png',
'/src/lib/assets/marca-hubsafe.png',
'/src/lib/assets/marca-ic-globall.png',
'/src/lib/assets/marca-ic-sindi.png',
'/src/lib/assets/marca-jusfy.png',
'/src/lib/assets/marca-sesc.png',
// Outras imagens importantes
'/src/lib/assets/cubes-plus.svg',
'/src/lib/assets/iphone-pix-mockup.png',
'/src/lib/assets/iphone-pix-mockup2.png',
'/src/lib/assets/banking-interface-mockup2.png',
'/src/lib/assets/qrcode-azul.png',
'/src/lib/assets/copy-link-pagamento.png',
// Ícones e SVGs críticos
'/src/lib/assets/pix-e-ted-azul.svg',
'/src/lib/assets/pagamentos-azul.svg',
'/src/lib/assets/cobranca.svg',
'/src/lib/assets/saldos-e-extratos.svg',
'/src/lib/assets/fluxo-de-aprovacao.svg',
'/src/lib/assets/conta-escrow-azul.svg',
'/src/lib/assets/cobranca-em-lote.svg',
'/src/lib/assets/gestao-de-usuarios.svg',
'/src/lib/assets/check.svg',
'/src/lib/assets/lock-icon.svg',
// App store badges
'/src/lib/assets/apple-store.svg',
'/src/lib/assets/google-play.svg',
// Logos da empresa
'/src/lib/assets/logo-basspago-preta.svg',
'/src/lib/assets/icon-slim-basspago.svg'
];
// Recursos para cache dinâmico (não críticos)
const dynamicCacheResources = [
'/src/lib/assets/case-1.webp',
'/src/lib/assets/case-2.webp',
'/src/lib/assets/case-3.webp',
'/src/lib/assets/case-4.webp',
'/src/lib/assets/case-5.webp',
'/src/lib/assets/case-6.webp',
'/src/lib/assets/payment-schedule-mockup.svg'
];
// Install event - Cache recursos críticos
self.addEventListener('install', (event) => {
console.log('[SW] Installing...');
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => {
console.log('[SW] Cache opened, adding critical resources...');
// Cache recursos críticos em lotes para evitar timeout
const batchSize = 10;
const batches = [];
for (let i = 0; i < urlsToCache.length; i += batchSize) {
batches.push(urlsToCache.slice(i, i + batchSize));
}
return batches.reduce((promise, batch) => {
return promise.then(() => {
console.log('[SW] Caching batch:', batch);
return cache.addAll(batch).catch((error) => {
console.warn('[SW] Failed to cache batch:', batch, error);
// Tenta cachear individualmente em caso de erro
return Promise.allSettled(
batch.map(url => cache.add(url).catch(e => console.warn('[SW] Failed to cache:', url, e)))
);
});
});
}, Promise.resolve());
})
.then(() => {
console.log('[SW] Critical resources cached successfully');
})
.catch((error) => {
console.error('[SW] Failed to cache critical resources:', error);
})
);
// Força a ativação imediata
self.skipWaiting();
});
// Activate event - Limpa caches antigos
self.addEventListener('activate', (event) => {
console.log('[SW] Activating...');
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (cacheName !== CACHE_NAME) {
console.log('[SW] Deleting old cache:', cacheName);
return caches.delete(cacheName);
}
})
);
}).then(() => {
console.log('[SW] Old caches cleaned');
// Toma controle de todas as abas abertas
return self.clients.claim();
})
);
});
// Fetch event - Estratégia de cache
self.addEventListener('fetch', (event) => {
const { request } = event;
const url = new URL(request.url);
// Ignora requests que não são GET
if (request.method !== 'GET') {
return;
}
// Ignora requests para outros domínios (exceto fonts)
if (url.origin !== location.origin && !url.hostname.includes('fonts')) {
return;
}
event.respondWith(
caches.match(request)
.then((cachedResponse) => {
// Se está no cache, retorna imediatamente
if (cachedResponse) {
console.log('[SW] Serving from cache:', request.url);
// Para recursos críticos, também faz fetch em background para atualizar
if (urlsToCache.includes(url.pathname)) {
fetch(request).then((response) => {
if (response.ok) {
caches.open(CACHE_NAME).then((cache) => {
cache.put(request, response.clone());
});
}
}).catch(() => {
// Ignora erros de network em background updates
});
}
return cachedResponse;
}
// Se não está no cache, faz fetch
console.log('[SW] Fetching from network:', request.url);
return fetch(request)
.then((response) => {
// Só cacheia responses válidos
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
// Cacheia recursos dinâmicos se estão na lista
if (dynamicCacheResources.includes(url.pathname) ||
url.pathname.includes('/src/lib/assets/')) {
const responseToCache = response.clone();
caches.open(CACHE_NAME)
.then((cache) => {
console.log('[SW] Caching dynamic resource:', request.url);
cache.put(request, responseToCache);
});
}
return response;
})
.catch((error) => {
console.error('[SW] Fetch failed:', request.url, error);
// Fallback para páginas HTML
if (request.headers.get('accept').includes('text/html')) {
return caches.match('/');
}
throw error;
});
})
);
});
// Background Sync para cache de recursos não críticos
self.addEventListener('sync', (event) => {
if (event.tag === 'background-cache') {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => {
console.log('[SW] Background caching dynamic resources...');
return Promise.allSettled(
dynamicCacheResources.map(url =>
cache.add(url).catch(e => console.warn('[SW] Background cache failed:', url, e))
)
);
})
);
}
});
// Message event para comunicação com a app
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
if (event.data && event.data.type === 'GET_CACHE_STATUS') {
caches.open(CACHE_NAME).then((cache) => {
return cache.keys();
}).then((keys) => {
event.ports[0].postMessage({
type: 'CACHE_STATUS',
cached: keys.length,
total: urlsToCache.length
});
});
}
});
// Periodic background sync (se suportado)
self.addEventListener('periodicsync', (event) => {
if (event.tag === 'cache-update') {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => {
console.log('[SW] Periodic cache update...');
return Promise.allSettled(
urlsToCache.map(url =>
fetch(url).then(response => {
if (response.ok) {
return cache.put(url, response);
}
}).catch(e => console.warn('[SW] Periodic update failed:', url, e))
)
);
})
);
}
});