easythemestore

How to Use Service Workers for Offline WordPress Sites

How to Use Service Workers for Offline WordPress Sites (2025 Guide)

Service Workers enable offline functionality, faster caching, and background sync for WordPress sites, transforming them into Progressive Web Apps (PWAs). This guide covers how to implement Service Workers in WordPress, from basic offline caching to advanced strategies like background sync and push notifications.


Why Use Service Workers in WordPress?

✅ Offline Access – Users can browse cached content without internet.
✅ Faster Load Times – Assets load from cache instead of the network.
✅ Background Sync – Submit forms (e.g., comments) when online again.
✅ Push Notifications – Engage users with updates. Our YouTube channel; https://www.youtube.com/@easythemestore


Step 1: Register a Service Worker

A. Create a Service Worker File (sw.js)

Place this in your theme’s root directory (e.g., /wp-content/themes/your-theme/sw.js):

const CACHE_NAME = 'wp-offline-v1';
const ASSETS_TO_CACHE = [
  '/',
  '/wp-content/themes/your-theme/style.css',
  '/wp-content/themes/your-theme/main.js',
  '/wp-includes/js/jquery/jquery.min.js',
  '/wp-content/uploads/2024/05/logo.png'
];

// Install & Cache Assets
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then((cache) => cache.addAll(ASSETS_TO_CACHE))
  );
});

// Fetch from Cache (Fallback to Network)
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request)
      .then((response) => response || fetch(event.request))
  );
});

B. Register the Service Worker in WordPress

Add this to your theme’s functions.php or a custom plugin:

function register_service_worker() {
  wp_enqueue_script(
    'sw-registration',
    get_template_directory_uri() . '/sw-register.js',
    [],
    '1.0',
    true
  );
}
add_action('wp_enqueue_scripts', 'register_service_worker');

Then create sw-register.js:

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

Step 2: Advanced Caching Strategies

A. Dynamic Caching (Cache API Responses)

Update sw.js to cache WordPress REST API calls:

self.addEventListener('fetch', (event) => {
  if (event.request.url.includes('/wp-json/')) {
    event.respondWith(
      caches.open('wp-api-cache').then((cache) => {
        return fetch(event.request)
          .then((response) => {
            cache.put(event.request, response.clone());
            return response;
          })
          .catch(() => caches.match(event.request));
      })
    );
  } else {
    event.respondWith(
      caches.match(event.request)
        .then((response) => response || fetch(event.request))
    );
  }
});

B. Stale-While-Revalidate (For Frequent Updates)

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.open('dynamic-cache').then((cache) => {
      return cache.match(event.request)
        .then((response) => {
          const fetchPromise = fetch(event.request).then((networkResponse) => {
            cache.put(event.request, networkResponse.clone());
            return networkResponse;
          });
          return response || fetchPromise;
        });
    })
  );
});

Step 3: Offline Fallback Page

Create an offline.html page and cache it:

// In sw.js
const OFFLINE_PAGE = '/offline.html';

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then((cache) => cache.add(OFFLINE_PAGE))
  );
});

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request)
      .then((response) => response || fetch(event.request))
      .catch(() => caches.match(OFFLINE_PAGE))
  );
});

Step 4: Background Sync (For Failed Requests)

A. Detect Failed POST Requests (e.g., Comments)

self.addEventListener('sync', (event) => {
  if (event.tag === 'sync-comments') {
    event.waitUntil(sendFailedComments());
  }
});

function sendFailedComments() {
  return fetch('/wp-json/wp/v2/comments', {
    method: 'POST',
    body: localStorage.getItem('pending_comment')
  });
}

B. Retry When Online

// In your theme's JS
if ('SyncManager' in window) {
  navigator.serviceWorker.ready.then((registration) => {
    document.getElementById('comment-form').addEventListener('submit', (e) => {
      e.preventDefault();
      const comment = new FormData(e.target);
      
      fetch('/wp-json/wp/v2/comments', {
        method: 'POST',
        body: comment
      }).catch(() => {
        localStorage.setItem('pending_comment', comment);
        registration.sync.register('sync-comments');
      });
    });
  });
}

Step 5: Push Notifications (Optional)

A. Request Notification Permission

// In your theme's JS
function requestNotificationPermission() {
  Notification.requestPermission().then((result) => {
    if (result === 'granted') {
      subscribeToPush();
    }
  });
}

function subscribeToPush() {
  navigator.serviceWorker.ready.then((registration) => {
    registration.pushManager.subscribe({
      userVisibleOnly: true,
      applicationServerKey: 'YOUR_VAPID_KEY'
    });
  });
}

B. Handle Push Events in sw.js

self.addEventListener('push', (event) => {
  const data = event.data.json();
  event.waitUntil(
    self.registration.showNotification(data.title, {
      body: data.message,
      icon: '/wp-content/uploads/2024/05/icon.png'
    })
  );
});

Best Practices

🔹 Cache Strategically – Don’t cache admin pages or sensitive data.
🔹 Update Cache on New Posts – Use post_updated hooks to refresh.
🔹 Test Offline Mode – Use Chrome DevTools → Application → Service Workers.


Final Thoughts

Service Workers turn WordPress into a true offline-capable PWA. Start with:
1️⃣ Basic caching (HTML/CSS/JS)
2️⃣ Advanced API caching
3️⃣ Background sync for forms

🚀 Pro Tip: Combine with Workbox for easier Service Worker management!