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

How to implement PWA offline functionality? What are the key steps required?

2月18日 21:53

PWA's offline functionality is one of its core features, mainly implemented through Service Worker and caching mechanisms. Here's a complete solution for implementing offline functionality:

Core Components of Offline Functionality

1. Service Worker

Service Worker is the foundation of offline functionality, capable of intercepting network requests and returning resources from cache.

2. Cache API

Used for storing and managing cached resources.

Steps to Implement Offline Functionality

Step 1: Register Service Worker

javascript
// Register in main thread if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/sw.js') .then(registration => { console.log('SW registered:', registration); }) .catch(error => { console.log('SW registration failed:', error); }); }); }

Step 2: Pre-cache Critical Resources

javascript
// sw.js const CACHE_NAME = 'my-pwa-v1'; const ASSETS_TO_CACHE = [ '/', '/index.html', '/styles/main.css', '/scripts/app.js', '/images/logo.png', '/offline.html' ]; self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME) .then(cache => { return cache.addAll(ASSETS_TO_CACHE); }) .then(() => { return self.skipWaiting(); }) ); });

Step 3: Implement Caching Strategy

javascript
self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request) .then(response => { // Cache hit, return directly if (response) { return response; } // Cache miss, request network return fetch(event.request) .then(response => { // Check if response is valid if (!response || response.status !== 200 || response.type !== 'basic') { return response; } // Clone response and cache const responseToCache = response.clone(); caches.open(CACHE_NAME) .then(cache => { cache.put(event.request, responseToCache); }); return response; }) .catch(() => { // Network request failed, return offline page if (event.request.mode === 'navigate') { return caches.match('/offline.html'); } }); }) ); });

Step 4: Create Offline Page

html
<!-- offline.html --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Offline</title> <style> body { display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; font-family: Arial, sans-serif; background: #f5f5f5; } .offline-container { text-align: center; padding: 40px; background: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .offline-icon { font-size: 64px; margin-bottom: 20px; } .offline-title { font-size: 24px; margin-bottom: 10px; color: #333; } .offline-message { color: #666; margin-bottom: 20px; } .retry-button { padding: 10px 20px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; } </style> </head> <body> <div class="offline-container"> <div class="offline-icon">📡</div> <h1 class="offline-title">You are currently offline</h1> <p class="offline-message">Please check your network connection and try again</p> <button class="retry-button" onclick="window.location.reload()">Reload</button> </div> <script> // Listen for network status changes window.addEventListener('online', () => { window.location.reload(); }); </script> </body> </html>

Step 5: Monitor Network Status

javascript
// Monitor network status in main thread window.addEventListener('online', () => { console.log('Network connected'); // Can perform operations here, like syncing data }); window.addEventListener('offline', () => { console.log('Network disconnected'); // Show offline notification showOfflineNotification(); }); function showOfflineNotification() { const notification = document.createElement('div'); notification.textContent = 'You are currently offline'; notification.style.cssText = ` position: fixed; top: 20px; left: 50%; transform: translateX(-50%); background: #ff9800; color: white; padding: 10px 20px; border-radius: 4px; z-index: 9999; `; document.body.appendChild(notification); setTimeout(() => { notification.remove(); }, 3000); }

Advanced Offline Features

1. Background Sync

javascript
// Register sync event self.addEventListener('sync', event => { if (event.tag === 'sync-data') { event.waitUntil(syncData()); } }); async function syncData() { // Get data stored while offline const offlineData = await getOfflineData(); // Sync to server for (const data of offlineData) { try { await fetch('/api/sync', { method: 'POST', body: JSON.stringify(data) }); // Sync successful, delete local data await removeOfflineData(data.id); } catch (error) { console.error('Sync failed:', error); } } } // Request sync in main thread navigator.serviceWorker.ready.then(registration => { registration.sync.register('sync-data'); });

2. IndexedDB for Storing Offline Data

javascript
// Open IndexedDB const dbPromise = idb.open('my-pwa-db', 1, upgradeDB => { upgradeDB.createObjectStore('offline-data', { keyPath: 'id' }); }); // Save offline data async function saveOfflineData(data) { const db = await dbPromise; await db.add('offline-data', data); } // Get offline data async function getOfflineData() { const db = await dbPromise; return await db.getAll('offline-data'); } // Delete offline data async function removeOfflineData(id) { const db = await dbPromise; await db.delete('offline-data', id); }

Best Practices for Offline Functionality

  1. Pre-cache Critical Resources: Ensure core functionality is available offline
  2. Provide Friendly Offline Page: Inform users of current status and provide solutions
  3. Monitor Network Status: Respond to network changes in time
  4. Implement Data Synchronization: Store data while offline, sync when online
  5. Set Reasonable Caching Strategy: Balance performance and freshness
  6. Test Offline Scenarios: Use Chrome DevTools Offline mode for testing
  7. Provide Network Status Indicator: Let users know current network status

Testing Offline Functionality

Test with Chrome DevTools:

  1. Open DevTools (F12)
  2. Switch to Network tab
  3. Check "Offline" mode
  4. Refresh page to test offline functionality
  5. Uncheck "Offline" to test recovery functionality
标签:PWA