Frontend Development 27 min read

Mastering Offline Caching with Service Workers: A Deep Dive into PWA Strategies

This article explains how Progressive Web Apps use Service Workers to provide offline access, installability, push notifications, and responsive layouts, and it walks through registration, caching strategies, dynamic cache management, expiration handling, and practical code examples for robust offline experiences.

JD Cloud Developers
JD Cloud Developers
JD Cloud Developers
Mastering Offline Caching with Service Workers: A Deep Dive into PWA Strategies

1. What is PWA

PWA (Progressive Web App) combines web and native app features using modern web technologies such as Service Workers and Web App Manifests to deliver an app‑like experience.

2. Service Worker

A Service Worker runs in the browser background, intercepts network requests, caches HTML, CSS, JavaScript, images and other assets, and can also handle push notifications and background sync.

Compared with a browser extension’s background script, a Service Worker operates independently of any page, cannot access the DOM directly, and is subject to stricter security permissions.

3. Registration

<code>&lt;!-- index.html --&gt;
<!DOCTYPE html>
<html>
<head>
  <title>Service Worker 示例</title>
</head>
<body>
  <script>
    if ('serviceWorker' in navigator) {
      window.addEventListener('load', function() {
        navigator.serviceWorker.register('/service-worker.js')
          .then(function(registration) {
            console.log('Service Worker 注册成功:', registration.scope);
          })
          .catch(function(error) {
            console.log('Service Worker 注册失败:', error);
          });
      });
    }
  </script>
</body>
</html>

// service-worker.js
const filesToCache = [
  '/',
  '/index.html',
  '/styles.css',
  '/script.js',
  '/image.jpg'
];

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('my-cache')
      .then(function(cache) {
        return cache.addAll(filesToCache);
      })
  );
});

self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.filter(function(cacheName) {
          return cacheName !== 'my-cache';
        }).map(function(cacheName) {
          return caches.delete(cacheName);
        })
      );
    })
  );
});

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

4. Usage

After registration, open Chrome DevTools → Application tab to see the active Service Worker and the cache named

my-cache

. When the page is refreshed in offline mode, the cached resources are served.

Service Worker in Chrome
Service Worker in Chrome

5. Determining Pre‑Cache Scope

For projects with many resources, list the core files in

filesToCache

and give the cache a versioned name (e.g.,

pre-cache-v1

). Dynamic resources are handled by a separate runtime cache.

6. Cache Strategies

Cache First – serve from cache, fall back to network.

Network First – try network, fall back to cache.

Cache Only – serve only from cache.

Network Only – always fetch from network.

Stale‑While‑Revalidate – return cached response immediately and update it in the background.

The article mainly uses the Cache First strategy for the pre‑cache and Stale‑While‑Revalidate for dynamic resources.

7. Dynamic Cache & Runtime Updates

<code>// New runtime cache name
const runtimeCacheName = 'runtime-cache-' + version;

self.addEventListener('fetch', function(event) {
  const {request} = event;
  if (isStaleWhileRevalidate(request)) {
    event.respondWith(handleFetch(request));
    return;
  }
  // default fallback
  event.respondWith(fetch(request));
});

function handleFetch(request) {
  return caches.match(request).then(function(response) {
    const fetchPromise = fetch(request).then(function(networkResponse) {
      if (networkResponse && networkResponse.status === 200) {
        const clone = networkResponse.clone();
        caches.open(runtimeCacheName).then(cache => cache.put(request, clone));
      }
      return networkResponse;
    });
    return response || fetchPromise;
  });
}</code>

8. Cache Expiration

Use Workbox’s

ExpirationPlugin

or implement a custom expiration check that stores a timestamp header (e.g.,

sw-save-date

) and removes entries after a defined max‑age.

<code>function isExpired(response, maxAge) {
  const saved = Number(response.headers.get('sw-save-date'));
  if (!saved) return false;
  return Date.now() > saved + maxAge * 1000;
}
</code>

9. Opaque Responses

Cross‑origin requests without CORS headers return opaque responses (status 0, unreadable body). To cache them, create a new

Request

with

mode: 'cors'

and appropriate credentials.

<code>const newRequest = request.url.endsWith('index.html')
  ? request
  : new Request(request, {mode: 'cors', credentials: 'omit'});
</code>

10. Cleanup & Fallback

Set a flag (

SW_FALLBACK

) to switch between registering the Service Worker and unregistering it when problems occur.

<code>if ('serviceWorker' in navigator) {
  if (!SW_FALLBACK) {
    navigator.serviceWorker.register('/eemf-service-worker.js')
      .then(reg => console.log('Service Worker 注册成功!'))
      .catch(err => console.log('Service Worker 注册失败:', err));
  } else {
    navigator.serviceWorker.getRegistration('/')
      .then(reg => {
        if (reg) reg.unregister().then(() => window.location.reload());
      });
  }
}
</code>

11. Conclusion

PWA offline caching via Service Workers offers a powerful way to improve load speed and reliability, but it requires careful versioning, cache management, and fallback strategies. A complete demo is available at https://github.com/suilang/PWA-demo .

References

Service Worker specification

Service Worker overview

Workbox documentation

GPT Q&A

JavaScriptPWAService Workeroffline cachingCache StrategiesProgressive Web App
JD Cloud Developers
Written by

JD Cloud Developers

JD Cloud Developers (Developer of JD Technology) is a JD Technology Group platform offering technical sharing and communication for AI, cloud computing, IoT and related developers. It publishes JD product technical information, industry content, and tech event news. Embrace technology and partner with developers to envision the future.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.