如何实现离线状态下PWA返回200状态码?
Got it, let's break down how to pull this off. The core tool here is the service worker—it's the backbone of offline functionality in PWAs, letting you intercept network requests and serve cached resources instead. Here's a step-by-step implementation that guarantees a 200 status code when your app is offline:
1. Register the Service Worker in Your Main App
First, you need to tell the browser to load and activate the service worker from your main app file. Add this code to your main JavaScript (e.g., app.js) or directly in your HTML's <script> tag:
if ('serviceWorker' in navigator) { window.addEventListener('load', async () => { try { const registration = await navigator.serviceWorker.register('/sw.js'); console.log('Service Worker registered successfully:', registration.scope); } catch (err) { console.error('Service Worker registration failed:', err); } }); }
2. Write the Service Worker Logic (sw.js)
Create a sw.js file in your app's root directory (this ensures it has scope over all your app's routes). This file handles caching your app's assets and intercepting requests to return cached content (with a 200 status) when offline.
// sw.js const CACHE_VERSION = 'pwa-offline-cache-v1'; const CACHED_ASSETS = [ '/', '/index.html', '/styles.css', '/app.js', '/offline.html' // Optional: Custom offline page for un-cached routes ]; // Install phase: Cache essential assets when the service worker is first added self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE_VERSION) .then(cache => cache.addAll(CACHED_ASSETS)) .then(() => self.skipWaiting()) // Activate the new service worker immediately ); }); // Activate phase: Clean up old caches when a new version is deployed self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then(cacheNames => { return Promise.all( cacheNames.filter(name => name !== CACHE_VERSION) .map(oldCache => caches.delete(oldCache)) ); }).then(() => self.clients.claim()) // Take control of all open app tabs ); }); // Fetch phase: Intercept requests and serve cached content offline self.addEventListener('fetch', (event) => { // Skip non-GET requests (we don't want to cache POST/PUT/etc.) if (event.request.method !== 'GET') return; event.respondWith( // Try to fetch from the network first fetch(event.request) .then(networkResponse => { // Update the cache with the fresh network response caches.open(CACHE_VERSION).then(cache => { cache.put(event.request, networkResponse.clone()); }); return networkResponse; }) .catch(() => { // If offline, try to return cached content return caches.match(event.request) .then(cachedResponse => { // If the requested asset is cached, return it (status 200) if (cachedResponse) { return cachedResponse; } // Fall back to the custom offline page if no cached asset exists return caches.match('/offline.html'); }); }) ); });
Critical Details to Ensure 200 Status Offline
- Cache All Core Assets: Make sure your main HTML, CSS, JS, and any offline fallback page are included in
CACHED_ASSETS. When these are requested offline, the service worker returns the cached version, which retains a 200 status code. - Fallback to Offline Page: If a user requests a route that isn't cached, returning a pre-cached
/offline.htmlensures you still send a 200 instead of a 404 or 503 error. - Test with DevTools: Use Chrome DevTools' Application > Service Workers panel to enable "Offline" mode, then refresh your app. Check the Network tab to confirm all requests return a 200 status code.
内容的提问来源于stack exchange,提问作者Sarah Elson

