// Service Worker registration with automatic update detection for Next.js // This ensures users always get the latest version after deployment type Config = { onUpdate?: (registration: ServiceWorkerRegistration) => void; onSuccess?: (registration: ServiceWorkerRegistration) => void; }; export function register(config?: Config) { if (typeof window !== 'undefined' && 'serviceWorker' in navigator) { // Wait for page load to avoid impacting initial page load performance window.addEventListener('load', () => { const swUrl = `/sw.js`; registerValidSW(swUrl, config); // Check for updates every hour setInterval(() => { checkForUpdates(swUrl); }, 60 * 60 * 1000); // 1 hour }); } } function registerValidSW(swUrl: string, config?: Config) { navigator.serviceWorker .register(swUrl) .then((registration) => { // Check for updates on initial registration registration.update(); registration.onupdatefound = () => { const installingWorker = registration.installing; if (installingWorker == null) { return; } installingWorker.onstatechange = () => { if (installingWorker.state === 'installed') { if (navigator.serviceWorker.controller) { // New content is available; please refresh console.log('New content available! Please refresh.'); // Execute onUpdate callback if (config && config.onUpdate) { config.onUpdate(registration); } } else { // Content is cached for offline use console.log('Content cached for offline use.'); // Execute onSuccess callback if (config && config.onSuccess) { config.onSuccess(registration); } } } }; }; }) .catch((error) => { console.error('Error during service worker registration:', error); }); } function checkForUpdates(swUrl: string) { navigator.serviceWorker .getRegistration(swUrl) .then((registration) => { if (registration) { registration.update(); } }) .catch((error) => { console.error('Error checking for service worker updates:', error); }); } export function unregister() { if (typeof window !== 'undefined' && 'serviceWorker' in navigator) { navigator.serviceWorker.ready .then((registration) => { registration.unregister(); }) .catch((error) => { console.error(error.message); }); } } // Force refresh when a new service worker is waiting export function skipWaitingAndReload() { if (typeof window !== 'undefined') { navigator.serviceWorker.ready.then((registration) => { if (registration.waiting) { // Tell the waiting service worker to skip waiting and become active registration.waiting.postMessage({ type: 'SKIP_WAITING' }); } }); // Listen for the controller change and reload navigator.serviceWorker.addEventListener('controllerchange', () => { window.location.reload(); }); } }