乐闻世界logo
搜索文章和话题

What is the lifecycle of Service Worker and how to implement offline caching?

2月21日 15:24

Service Worker is a special type of Web Worker that runs as a network proxy between the browser and server, providing offline capabilities, push notifications, and background synchronization.

Core Concepts of Service Worker

Characteristics

  • Runs independently of page lifecycle
  • Intercepts and handles network requests
  • Must run in HTTPS environment (localhost is an exception)
  • Can implement offline caching and resource preloading
  • Supports push notifications and background synchronization

Registering Service Worker

javascript
// Check browser support if ('serviceWorker' in navigator) { // Register Service Worker navigator.serviceWorker.register('/service-worker.js') .then(function(registration) { console.log('Service Worker registered successfully:', registration.scope); }) .catch(function(error) { console.log('Service Worker registration failed:', error); }); }

Service Worker Lifecycle

1. Install

javascript
// service-worker.js const CACHE_NAME = 'my-cache-v1'; const urlsToCache = [ '/', '/styles/main.css', '/script/main.js', '/images/logo.png' ]; self.addEventListener('install', function(event) { // event.waitUntil delays installation completion event.waitUntil( caches.open(CACHE_NAME) .then(function(cache) { console.log('Cache opened'); return cache.addAll(urlsToCache); }) ); // Immediately activate new Service Worker self.skipWaiting(); });

2. Activate

javascript
self.addEventListener('activate', function(event) { event.waitUntil( caches.keys().then(function(cacheNames) { return Promise.all( cacheNames.map(function(cacheName) { // Delete old version caches if (cacheName !== CACHE_NAME) { console.log('Deleting old cache:', cacheName); return caches.delete(cacheName); } }) ); }) ); // Immediately control all clients self.clients.claim(); });

3. Fetch

javascript
self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request) .then(function(response) { // Cache hit, return cache if (response) { return response; } // Cache miss, make network request return fetch(event.request).then( function(response) { // Check if valid response if (!response || response.status !== 200 || response.type !== 'basic') { return response; } // Clone response (response stream can only be used once) const responseToCache = response.clone(); caches.open(CACHE_NAME) .then(function(cache) { cache.put(event.request, responseToCache); }); return response; } ); }) ); });

Caching Strategies

1. Cache First

javascript
self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request) .then(function(response) { return response || fetch(event.request); }) ); });

2. Network First

javascript
self.addEventListener('fetch', function(event) { event.respondWith( fetch(event.request) .then(function(response) { const responseToCache = response.clone(); caches.open(CACHE_NAME).then(function(cache) { cache.put(event.request, responseToCache); }); return response; }) .catch(function() { return caches.match(event.request); }) ); });

3. Network Only

javascript
self.addEventListener('fetch', function(event) { event.respondWith(fetch(event.request)); });

4. Cache Only

javascript
self.addEventListener('fetch', function(event) { event.respondWith(caches.match(event.request)); });

5. Stale While Revalidate

javascript
self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request).then(function(cachedResponse) { const fetchPromise = fetch(event.request).then(function(networkResponse) { caches.open(CACHE_NAME).then(function(cache) { cache.put(event.request, networkResponse.clone()); }); return networkResponse; }); return cachedResponse || fetchPromise; }) ); });

Push Notifications

Subscribe to Push

javascript
// Main thread function subscribeUser() { return navigator.serviceWorker.register('/service-worker.js') .then(function(registration) { const subscribeOptions = { userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array( 'BEl62iUYgUivxIkv69yViEuiBIa-IbRMhKDbjjVdMlzQJd0_...' ) }; return registration.pushManager.subscribe(subscribeOptions); }) .then(function(pushSubscription) { console.log('Received push subscription:', pushSubscription); return pushSubscription; }); }

Handle Push Messages

javascript
// service-worker.js self.addEventListener('push', function(event) { const options = { body: event.data ? event.data.text() : 'New message', icon: '/images/icon.png', badge: '/images/badge.png', vibrate: [100, 50, 100], data: { dateOfArrival: Date.now(), primaryKey: 1 } }; event.waitUntil( self.registration.showNotification('Push Notification', options) ); }); // Handle notification click self.addEventListener('notificationclick', function(event) { event.notification.close(); event.waitUntil( clients.openWindow('/') ); });

Background Sync

Register Sync Event

javascript
// Main thread navigator.serviceWorker.ready.then(function(registration) { registration.sync.register('sync-messages'); });

Handle Sync Event

javascript
// service-worker.js self.addEventListener('sync', function(event) { if (event.tag === 'sync-messages') { event.waitUntil(syncMessages()); } }); function syncMessages() { return fetch('/api/sync-messages', { method: 'POST', body: JSON.stringify(getPendingMessages()) }); }

Debugging Service Worker

Chrome DevTools

  1. Open Chrome DevTools
  2. Switch to "Application" panel
  3. Select "Service Workers" on the left
  4. Can view status, update, unregister, etc.

Update Service Worker

javascript
// Manual update navigator.serviceWorker.ready.then(function(registration) { registration.update(); }); // Listen for updates navigator.serviceWorker.addEventListener('controllerchange', function() { console.log('Service Worker updated'); window.location.reload(); });

Best Practices

  1. HTTPS Requirement: Must use HTTPS in production environment
  2. Cache Version Management: Use version numbers to manage caches
  3. Error Handling: Add comprehensive error handling
  4. Progressive Enhancement: Ensure normal operation in browsers without Service Worker support
  5. Resource Cleanup: Clean up old version caches in time
  6. Performance Optimization: Choose caching strategies appropriately
  7. Security: Verify request sources to prevent CSRF attacks
标签:Web Worker