Now.js Framework Documentation

Now.js Framework Documentation

ServiceWorkerManager - Service Worker Management

EN 31 Oct 2025 01:23

ServiceWorkerManager - Service Worker Management

Documentation for ServiceWorkerManager, a service worker management system for offline functionality and push notifications.

📋 Table of Contents

  1. Overview
  2. Installation and Import
  3. Basic Usage
  4. Cache Management
  5. Caching Strategies
  6. Push Notifications
  7. Offline Support
  8. Updates and Lifecycle
  9. Configuration
  10. Usage Examples
  11. API Reference
  12. Best Practices

Overview

ServiceWorkerManager is a service worker management system that enables offline functionality and push notifications for applications.

Key Features

  • Service Worker Registration: Automatic service worker registration
  • Auto Caching: Automatically cache JavaScript, CSS, images
  • Caching Strategies: Support for network-first, cache-first, stale-while-revalidate
  • Push Notifications: Push notification support with VAPID
  • Offline Support: Full offline mode
  • Auto Updates: Automatic service worker update checks
  • Update Notifications: Notify users of new versions
  • Cache Management: Manual cache control
  • Event System: Emit lifecycle events
  • Debug Mode: Debug mode for development

Use Cases

Suitable for:

  • Progressive Web Apps (PWA)
  • Offline-first applications
  • Applications with push notifications
  • Applications requiring cache control
  • Performance optimization
  • Mobile web applications

Installation and Import

ServiceWorkerManager loads with Now.js Framework:

// No need to import - ready to use immediately
console.log(window.ServiceWorkerManager); // ServiceWorkerManager object

// Access through Now.js
const swManager = Now.getManager('serviceWorker');

Dependencies

ServiceWorkerManager requires these dependencies:

  • ErrorManager - For error handling (optional)
  • NotificationManager - For showing notifications (optional)
  • EventManager - For emitting events (optional)
  • Service Worker File - /service-worker.js

Browser Requirements

ServiceWorkerManager requires browsers that support:

  • Service Worker API
  • PushManager API (for push notifications)
  • Cache API
// Check browser support
if (ServiceWorkerManager.isSupported()) {
  console.log('Service Worker is supported');
} else {
  console.log('Service Worker is not supported');
}

Basic Usage

1. Initialization

// Basic initialization
await ServiceWorkerManager.init({
  enabled: true,
  serviceWorkerPath: '/service-worker.js',
  scope: '/',
  version: '1.0.0',
  cacheName: 'my-app-cache-v1',
  debug: true
});

// Check status
console.log(ServiceWorkerManager.getStatus());

2. Check Status

// Check if service worker is ready
const status = ServiceWorkerManager.getStatus();
console.log('Initialized:', status.initialized);
console.log('Status:', status.status);
console.log('Offline Ready:', status.offlineReady);
console.log('Push Enabled:', status.pushEnabled);

3. Listen to Events

// Service worker registered
Now.on('serviceworker:registered', (data) => {
  console.log('Service worker registered:', data.registration);
});

// Update found
Now.on('serviceworker:update-found', () => {
  console.log('New version available');
});

// State change
Now.on('serviceworker:state-change', (data) => {
  console.log('State changed:', data.state);
});

// Offline ready
Now.on('serviceworker:offline-ready', () => {
  console.log('App is ready for offline use');
});

// Error
Now.on('serviceworker:error', (error) => {
  console.error('Service worker error:', error);
});

4. Manual Update

// Force update service worker
await ServiceWorkerManager.update();

// Skip waiting and activate immediately
await ServiceWorkerManager.skipWaiting();

Cache Management

Precache Configuration

// Define files to precache
await ServiceWorkerManager.init({
  enabled: true,
  precache: [
    '/',
    '/index.html',
    '/css/styles.css',
    '/js/app.js',
    '/images/logo.png'
  ]
});

Cache Patterns

// Define patterns for auto-caching
await ServiceWorkerManager.init({
  enabled: true,
  cachePatterns: [
    /\.js$/,      // JavaScript files
    /\.css$/,     // CSS files
    /\.html$/,    // HTML files
    /\.json$/,    // JSON files
    /\.png$/,     // PNG images
    /\.jpe?g$/,   // JPEG images
    /\.svg$/,     // SVG images
    /\.woff2?$/,  // Web fonts
    /\.ttf$/      // TrueType fonts
  ]
});

Exclude from Cache

// Define files to exclude from cache
await ServiceWorkerManager.init({
  enabled: true,
  excludeFromCache: [
    /\/api\//,        // API calls
    /analytics/,      // Analytics
    /\.php$/,         // PHP files
    /admin/           // Admin pages
  ]
});

Manual Cache

// Cache URLs manually
const urls = [
  '/page1.html',
  '/page2.html',
  '/images/banner.jpg'
];

await ServiceWorkerManager.cacheUrls(urls);

Clear Cache

// Clear all cache
await ServiceWorkerManager.clearCache();

Caching Strategies

Strategy Types

ServiceWorkerManager supports multiple caching strategies:

  1. network-first: Try network first, fallback to cache
  2. cache-first: Use cache first, fallback to network
  3. stale-while-revalidate: Use cache immediately, update in background

Configure Strategies

await ServiceWorkerManager.init({
  enabled: true,

  // Network-first for API calls
  networkFirst: [
    /\/api\//,
    /\.json$/
  ],

  // Custom strategies for specific paths
  strategies: {
    '/api/': 'network-first',           // API - network first
    '/images/': 'cache-first',          // Images - cache first
    '/css/': 'stale-while-revalidate',  // CSS - stale while revalidate
    '/js/': 'stale-while-revalidate'    // JS - stale while revalidate
  }
});

Strategy Examples

Network First

// Suitable for API calls and dynamic content
await ServiceWorkerManager.init({
  enabled: true,
  strategies: {
    '/api/': 'network-first',
    '/data/': 'network-first'
  }
});

Cache First

// Suitable for static assets
await ServiceWorkerManager.init({
  enabled: true,
  strategies: {
    '/images/': 'cache-first',
    '/fonts/': 'cache-first',
    '/icons/': 'cache-first'
  }
});

Stale While Revalidate

// Suitable for frequently updated content
await ServiceWorkerManager.init({
  enabled: true,
  strategies: {
    '/css/': 'stale-while-revalidate',
    '/js/': 'stale-while-revalidate'
  }
});

Push Notifications

Enable Push Notifications

// Enable push notifications
await ServiceWorkerManager.init({
  enabled: true,
  push: {
    enabled: true,
    publicKey: 'YOUR_VAPID_PUBLIC_KEY',
    userVisibleOnly: true
  }
});

Subscribe to Push

// Subscribe user to push notifications
try {
  const subscription = await ServiceWorkerManager.subscribePush();
  console.log('Push subscription:', subscription);

  // Send subscription to server
  await sendSubscriptionToServer(subscription);
} catch (error) {
  console.error('Failed to subscribe:', error);
}

Unsubscribe from Push

// Unsubscribe from push notifications
await ServiceWorkerManager.unsubscribePush();
console.log('Unsubscribed from push notifications');

Check Push Status

// Check if push notifications are enabled
if (ServiceWorkerManager.isPushEnabled()) {
  console.log('Push notifications are enabled');
} else {
  console.log('Push notifications are disabled');
}

Push Events

// Push subscribed
Now.on('serviceworker:push-subscribed', (data) => {
  console.log('Subscribed to push:', data.subscription);

  // Send to server
  sendToServer(data.subscription);
});

// Push unsubscribed
Now.on('serviceworker:push-unsubscribed', () => {
  console.log('Unsubscribed from push');
});

Offline Support

Check Offline Ready

// Check if ready for offline use
if (ServiceWorkerManager.isOfflineReady()) {
  console.log('App is ready for offline use');
} else {
  console.log('App is not ready for offline use yet');
}

Offline Content

// Define content for offline mode
await ServiceWorkerManager.init({
  enabled: true,
  offlineContent: `
    <div class="offline-message">
      <h1>You are offline</h1>
      <p>Some features may not be available</p>
    </div>
  `
});

Offline Event

// Listen for offline ready event
Now.on('serviceworker:offline-ready', () => {
  console.log('Application is ready for offline use');
  showOfflineReadyMessage();
});

Network Detection

// Monitor network status
window.addEventListener('online', () => {
  console.log('Network connection restored');
  ServiceWorkerManager.update(); // Check for updates
});

window.addEventListener('offline', () => {
  console.log('Network connection lost');
  showOfflineMessage();
});

Updates and Lifecycle

Auto Update Checks

// Define interval for update checks
await ServiceWorkerManager.init({
  enabled: true,
  updateInterval: 24 * 60 * 60 * 1000, // 24 hours
  notifyOnUpdate: true
});

Manual Update Check

// Force update check
await ServiceWorkerManager.update();

Update Notification

// Update notification shows automatically when update is available
await ServiceWorkerManager.init({
  enabled: true,
  notifyOnUpdate: true  // Show notification
});

// Disable notification
await ServiceWorkerManager.init({
  enabled: true,
  notifyOnUpdate: false
});

Skip Waiting

// Force service worker to activate immediately
await ServiceWorkerManager.skipWaiting();

// Reload page to apply update
window.location.reload();

Lifecycle Events

// State changes
Now.on('serviceworker:state-change', (data) => {
  console.log('State:', data.state); // 'installed', 'activated', 'redundant'
  console.log('Status:', data.status);
});

// Update found
Now.on('serviceworker:update-found', () => {
  console.log('New version is installing');
});

// Registered
Now.on('serviceworker:registered', (data) => {
  console.log('Service worker registered');
});

// Unregistered
Now.on('serviceworker:unregistered', () => {
  console.log('Service worker unregistered');
});

Unregister Service Worker

// Unregister service worker
const success = await ServiceWorkerManager.unregister();
if (success) {
  console.log('Service worker unregistered successfully');
}

Configuration

Configuration Options

const config = {
  // Enable/disable service worker
  enabled: true,

  // Service worker file location
  serviceWorkerPath: '/service-worker.js',

  // Service worker scope
  scope: '/',

  // Version
  version: '1.0.0',

  // Cache name
  cacheName: 'my-app-cache-v1',

  // Debug mode
  debug: true,

  // Update interval (ms)
  updateInterval: 24 * 60 * 60 * 1000, // 24 hours

  // Precache URLs
  precache: [
    '/',
    '/index.html',
    '/css/styles.css',
    '/js/app.js'
  ],

  // Auto-cache JavaScript files
  cacheJavascriptFiles: true,

  // Cache patterns
  cachePatterns: [
    /\.js$/,
    /\.css$/,
    /\.html$/,
    /\.json$/,
    /\.png$/,
    /\.jpe?g$/,
    /\.svg$/,
    /\.woff2?$/,
    /\.ttf$/
  ],

  // Network-first patterns
  networkFirst: [
    /\/api\//,
    /\.json$/
  ],

  // Exclude from cache
  excludeFromCache: [
    /analytics/,
    /\.php$/
  ],

  // Notify on update
  notifyOnUpdate: true,

  // Offline content
  offlineContent: null,

  // Push notifications
  push: {
    enabled: false,
    publicKey: null,
    userVisibleOnly: true
  },

  // Caching strategies
  strategies: {
    '/api/': 'network-first',
    '/images/': 'cache-first',
    '/css/': 'stale-while-revalidate'
  }
};

await ServiceWorkerManager.init(config);

Usage Examples

1. Basic PWA Setup

// Initialize service worker for PWA
await ServiceWorkerManager.init({
  enabled: true,
  serviceWorkerPath: '/service-worker.js',
  scope: '/',
  version: '1.0.0',
  cacheName: 'pwa-cache-v1',
  debug: false,
  precache: [
    '/',
    '/index.html',
    '/css/styles.css',
    '/js/app.js',
    '/manifest.json',
    '/images/icon-192.png',
    '/images/icon-512.png'
  ],
  notifyOnUpdate: true
});

// Listen for offline ready
Now.on('serviceworker:offline-ready', () => {
  showNotification('App is ready for offline use!');
});

2. E-commerce Application

// E-commerce with smart caching
await ServiceWorkerManager.init({
  enabled: true,
  cacheName: 'ecommerce-cache-v1',

  // Precache critical pages
  precache: [
    '/',
    '/products',
    '/cart',
    '/checkout'
  ],

  // Caching strategies
  strategies: {
    '/api/products': 'network-first',      // Products - fresh data
    '/api/cart': 'network-first',          // Cart - always fresh
    '/images/products/': 'cache-first',    // Product images - cache
    '/static/': 'cache-first',             // Static assets - cache
    '/css/': 'stale-while-revalidate',     // CSS - stale ok
    '/js/': 'stale-while-revalidate'       // JS - stale ok
  },

  // Exclude checkout from cache
  excludeFromCache: [
    /\/api\/checkout/,
    /\/api\/payment/
  ],

  // Push notifications for order updates
  push: {
    enabled: true,
    publicKey: 'YOUR_VAPID_PUBLIC_KEY'
  }
});

// Subscribe to push for order notifications
const subscription = await ServiceWorkerManager.subscribePush();
await api.saveSubscription(subscription);

3. News/Blog Application

// News app with offline reading
await ServiceWorkerManager.init({
  enabled: true,
  cacheName: 'news-cache-v1',

  // Cache patterns
  cachePatterns: [
    /\.html$/,
    /\.css$/,
    /\.js$/,
    /\/articles\/.+/,  // Article pages
    /\/images\/.+/     // Images
  ],

  // Network first for fresh content
  networkFirst: [
    /\/api\/articles/,
    /\/api\/latest/
  ],

  // Stale while revalidate for articles
  strategies: {
    '/articles/': 'stale-while-revalidate',
    '/images/': 'cache-first'
  },

  // Update check every hour
  updateInterval: 60 * 60 * 1000,

  // Notify on new articles
  notifyOnUpdate: true
});

// Push notifications for breaking news
await ServiceWorkerManager.subscribePush();

4. Dashboard Application

// Dashboard with API caching
await ServiceWorkerManager.init({
  enabled: true,
  cacheName: 'dashboard-cache-v1',

  // Precache dashboard pages
  precache: [
    '/dashboard',
    '/dashboard/analytics',
    '/dashboard/reports',
    '/dashboard/settings'
  ],

  // Network first for data
  networkFirst: [
    /\/api\/dashboard/,
    /\/api\/analytics/,
    /\.json$/
  ],

  // Cache static assets
  strategies: {
    '/static/': 'cache-first',
    '/charts/': 'cache-first',
    '/api/': 'network-first'
  },

  // Don't cache sensitive data
  excludeFromCache: [
    /\/api\/user\/sensitive/,
    /\/api\/admin/
  ],

  debug: true
});

// Handle offline mode
Now.on('serviceworker:offline-ready', () => {
  console.log('Dashboard ready for offline use');
});

window.addEventListener('offline', () => {
  showBanner('You are offline. Some features may be limited.');
});

5. Custom Update Handling

// Custom update prompt
await ServiceWorkerManager.init({
  enabled: true,
  notifyOnUpdate: false  // Disable default notification
});

// Custom update UI
Now.on('serviceworker:update-found', () => {
  showUpdateDialog({
    title: 'New Version Available',
    message: 'A new version is ready. Update now?',
    onConfirm: async () => {
      await ServiceWorkerManager.skipWaiting();
      window.location.reload();
    },
    onCancel: () => {
      console.log('Update postponed');
    }
  });
});

6. Cache Management UI

// Cache management interface
class CacheManager {
  async init() {
    await ServiceWorkerManager.init({
      enabled: true,
      debug: true
    });

    this.renderUI();
  }

  renderUI() {
    const container = document.querySelector('#cache-manager');
    container.innerHTML = `
      <h2>Cache Management</h2>
      <div class="cache-info">
        <p>Status: <span id="cache-status"></span></p>
        <p>Offline Ready: <span id="offline-status"></span></p>
      </div>
      <div class="cache-actions">
        <button id="clear-cache">Clear Cache</button>
        <button id="update-sw">Check for Updates</button>
        <button id="cache-urls">Cache Current Page</button>
      </div>
    `;

    this.updateStatus();
    this.setupEvents();
  }

  updateStatus() {
    const status = ServiceWorkerManager.getStatus();
    document.querySelector('#cache-status').textContent = status.status;
    document.querySelector('#offline-status').textContent =
      status.offlineReady ? 'Yes' : 'No';
  }

  setupEvents() {
    document.querySelector('#clear-cache').addEventListener('click', async () => {
      await ServiceWorkerManager.clearCache();
      alert('Cache cleared!');
      this.updateStatus();
    });

    document.querySelector('#update-sw').addEventListener('click', async () => {
      await ServiceWorkerManager.update();
      alert('Checking for updates...');
    });

    document.querySelector('#cache-urls').addEventListener('click', async () => {
      const currentUrl = window.location.href;
      await ServiceWorkerManager.cacheUrls([currentUrl]);
      alert('Current page cached!');
    });
  }
}

const cacheManager = new CacheManager();
cacheManager.init();

7. Progressive Enhancement

// Check support and enable features progressively
async function initializeApp() {
  // Check service worker support
  if (!ServiceWorkerManager.isSupported()) {
    console.log('Service Worker not supported, running in online-only mode');
    return;
  }

  // Initialize service worker
  await ServiceWorkerManager.init({
    enabled: true,
    cacheName: 'app-cache-v1',
    debug: true
  });

  // Enable offline features
  Now.on('serviceworker:offline-ready', () => {
    enableOfflineFeatures();
    showOfflineBadge();
  });

  // Enable push notifications if supported
  if ('PushManager' in window) {
    await setupPushNotifications();
  }
}

async function setupPushNotifications() {
  await ServiceWorkerManager.init({
    push: {
      enabled: true,
      publicKey: 'YOUR_VAPID_PUBLIC_KEY'
    }
  });

  // Ask for permission
  const permission = await Notification.requestPermission();
  if (permission === 'granted') {
    const subscription = await ServiceWorkerManager.subscribePush();
    await sendSubscriptionToServer(subscription);
  }
}

initializeApp();

8. Network Status Indicator

// Network status with service worker
class NetworkStatus {
  constructor() {
    this.indicator = null;
    this.init();
  }

  async init() {
    await ServiceWorkerManager.init({
      enabled: true
    });

    this.createIndicator();
    this.setupListeners();
  }

  createIndicator() {
    this.indicator = document.createElement('div');
    this.indicator.className = 'network-indicator';
    document.body.appendChild(this.indicator);

    this.updateIndicator();
  }

  setupListeners() {
    window.addEventListener('online', () => {
      this.updateIndicator();
      ServiceWorkerManager.update();
    });

    window.addEventListener('offline', () => {
      this.updateIndicator();
    });

    Now.on('serviceworker:offline-ready', () => {
      this.updateIndicator();
    });
  }

  updateIndicator() {
    const isOnline = navigator.onLine;
    const isOfflineReady = ServiceWorkerManager.isOfflineReady();

    if (isOnline) {
      this.indicator.textContent = '● Online';
      this.indicator.className = 'network-indicator online';
    } else if (isOfflineReady) {
      this.indicator.textContent = '● Offline (Cached)';
      this.indicator.className = 'network-indicator offline-ready';
    } else {
      this.indicator.textContent = '● Offline';
      this.indicator.className = 'network-indicator offline';
    }
  }
}

new NetworkStatus();

9. Background Sync

// Background sync for form submissions
class BackgroundSync {
  constructor() {
    this.pendingRequests = [];
    this.init();
  }

  async init() {
    await ServiceWorkerManager.init({
      enabled: true
    });

    // Listen for online event
    window.addEventListener('online', () => {
      this.syncPendingRequests();
    });
  }

  async submitForm(formData) {
    if (navigator.onLine) {
      // Online - submit directly
      return await this.sendRequest(formData);
    } else {
      // Offline - queue for later
      this.pendingRequests.push(formData);
      this.savePendingRequests();
      return {queued: true};
    }
  }

  async syncPendingRequests() {
    const requests = this.loadPendingRequests();

    for (const request of requests) {
      try {
        await this.sendRequest(request);
        this.removePendingRequest(request);
      } catch (error) {
        console.error('Sync failed:', error);
      }
    }
  }

  async sendRequest(data) {
    // Send to server
    return await fetch('/api/submit', {
      method: 'POST',
      body: JSON.stringify(data)
    });
  }

  savePendingRequests() {
    localStorage.setItem('pendingRequests',
      JSON.stringify(this.pendingRequests));
  }

  loadPendingRequests() {
    const data = localStorage.getItem('pendingRequests');
    return data ? JSON.parse(data) : [];
  }

  removePendingRequest(request) {
    this.pendingRequests = this.pendingRequests.filter(r => r !== request);
    this.savePendingRequests();
  }
}

const bgSync = new BackgroundSync();

10. Version Management

// Version management and migration
class VersionManager {
  async init() {
    const currentVersion = '2.0.0';
    const cachedVersion = localStorage.getItem('app-version');

    await ServiceWorkerManager.init({
      enabled: true,
      version: currentVersion,
      cacheName: `app-cache-${currentVersion}`
    });

    // Check for version upgrade
    if (cachedVersion && cachedVersion !== currentVersion) {
      await this.migrateVersion(cachedVersion, currentVersion);
    }

    localStorage.setItem('app-version', currentVersion);
  }

  async migrateVersion(oldVersion, newVersion) {
    console.log(`Migrating from ${oldVersion} to ${newVersion}`);

    // Clear old cache
    await ServiceWorkerManager.clearCache();

    // Unregister old service worker
    await ServiceWorkerManager.unregister();

    // Register new service worker
    await ServiceWorkerManager.init({
      enabled: true,
      version: newVersion,
      cacheName: `app-cache-${newVersion}`
    });

    // Migrate data if needed
    await this.migrateData(oldVersion, newVersion);

    // Notify user
    showNotification(`Upgraded to version ${newVersion}`);
  }

  async migrateData(oldVersion, newVersion) {
    // Implement data migration logic
    console.log('Migrating data...');
  }
}

const versionManager = new VersionManager();
versionManager.init();

API Reference

Configuration

{
  enabled: boolean,                  // Enable/disable service worker
  serviceWorkerPath: string,        // Path to service worker file
  scope: string,                    // Service worker scope
  version: string,                  // Version
  cacheName: string,               // Cache name
  debug: boolean,                  // Debug mode
  updateInterval: number,          // Update check interval (ms)
  precache: string[],              // URLs to precache
  cacheJavascriptFiles: boolean,   // Auto-cache JS files
  cachePatterns: RegExp[],         // Cache patterns
  networkFirst: RegExp[],          // Network-first patterns
  excludeFromCache: RegExp[],      // Exclude patterns
  notifyOnUpdate: boolean,         // Show update notification
  offlineContent: string | null,   // Offline content HTML

  push: {
    enabled: boolean,              // Enable push notifications
    publicKey: string | null,      // VAPID public key
    userVisibleOnly: boolean       // User visible only
  },

  strategies: {                    // Caching strategies
    [path: string]: 'network-first' | 'cache-first' | 'stale-while-revalidate'
  }
}

Methods

Initialization

// Initialize service worker
init(options?: object): Promise<ServiceWorkerManager>

// Check if supported
isSupported(): boolean

Cache Management

// Cache URLs manually
cacheUrls(urls: string[]): Promise<boolean>

// Clear cache
clearCache(): Promise<boolean>

Updates

// Check for updates
update(): Promise<boolean>

// Skip waiting and activate
skipWaiting(): Promise<boolean>

// Unregister service worker
unregister(): Promise<boolean>

Push Notifications

// Subscribe to push
subscribePush(): Promise<PushSubscription>

// Unsubscribe from push
unsubscribePush(): Promise<boolean>

// Check if push enabled
isPushEnabled(): boolean

Status

// Check if offline ready
isOfflineReady(): boolean

// Get status
getStatus(): {
  supported: boolean,
  initialized: boolean,
  status: string,
  offlineReady: boolean,
  registration: ServiceWorkerRegistration | null,
  lastUpdateCheck: number,
  errors: number,
  pushEnabled: boolean
}

Events

// Service worker registered
'serviceworker:registered' -> {
  registration: ServiceWorkerRegistration
}

// Update found
'serviceworker:update-found' -> {
  registration: ServiceWorkerRegistration
}

// State change
'serviceworker:state-change' -> {
  state: string,
  status: string
}

// Offline ready
'serviceworker:offline-ready'

// Error
'serviceworker:error' -> {
  message: string,
  stack: string,
  context: string,
  timestamp: number
}

// Push subscribed
'serviceworker:push-subscribed' -> {
  subscription: PushSubscription
}

// Push unsubscribed
'serviceworker:push-unsubscribed'

// Message from service worker
'serviceworker:message' -> {
  type: string,
  payload: any
}

// Service worker unregistered
'serviceworker:unregistered'

State

{
  initialized: boolean,                     // Initialized
  registration: ServiceWorkerRegistration | null,  // Registration
  updateFound: boolean,                     // Update found
  installingWorker: ServiceWorker | null,   // Installing worker
  offlineReady: boolean,                    // Offline ready
  lastUpdateCheck: number,                  // Last update check timestamp
  status: string,                          // Current status
  errors: Array,                           // Error history
  pushEnabled: boolean,                    // Push enabled
  pushSubscription: PushSubscription | null // Push subscription
}

Best Practices

1. ✅ Use Appropriate Caching Strategies

// ✅ Good: different strategies for different content
await ServiceWorkerManager.init({
  strategies: {
    '/api/': 'network-first',        // API - always fresh
    '/images/': 'cache-first',       // Images - cache preferred
    '/css/': 'stale-while-revalidate' // CSS - stale ok
  }
});

// ❌ Bad: cache everything the same way
await ServiceWorkerManager.init({
  strategies: {
    '/': 'cache-first'
  }
});

2. ✅ Precache Critical Resources

// ✅ Good: precache essential files
await ServiceWorkerManager.init({
  precache: [
    '/',
    '/index.html',
    '/css/critical.css',
    '/js/app.js',
    '/manifest.json'
  ]
});

// ❌ Bad: precache too many files
await ServiceWorkerManager.init({
  precache: [
    // 100+ files - will slow down initial load
  ]
});

3. ✅ Version Your Cache

// ✅ Good: version in cache name
await ServiceWorkerManager.init({
  version: '1.0.0',
  cacheName: 'my-app-cache-v1'
});

// When updating:
await ServiceWorkerManager.init({
  version: '1.1.0',
  cacheName: 'my-app-cache-v1.1'
});

4. ✅ Exclude Sensitive Data

// ✅ Good: don't cache sensitive data
await ServiceWorkerManager.init({
  excludeFromCache: [
    /\/api\/user\/sensitive/,
    /\/api\/admin/,
    /\/api\/payment/,
    /\.php$/
  ]
});

5. ✅ Handle Updates Gracefully

// ✅ Good: notify and let user decide
Now.on('serviceworker:update-found', () => {
  showNotification('New version available', {
    action: 'Reload',
    onAction: () => {
      ServiceWorkerManager.skipWaiting();
      window.location.reload();
    }
  });
});

// ❌ Bad: force reload immediately
Now.on('serviceworker:update-found', () => {
  window.location.reload();
});

6. ✅ Use Debug Mode in Development

// ✅ Good: debug in development
const isDev = window.location.hostname === 'localhost';

await ServiceWorkerManager.init({
  debug: isDev,
  updateInterval: isDev ? 10000 : 86400000 // 10s vs 24h
});

7. ✅ Monitor Errors

// ✅ Good: track errors
Now.on('serviceworker:error', (error) => {
  console.error('Service worker error:', error);

  // Send to error tracking service
  if (window.ErrorTracker) {
    ErrorTracker.log(error);
  }
});

8. ✅ Test Offline Functionality

// ✅ Good: test offline
if (ServiceWorkerManager.isOfflineReady()) {
  console.log('✓ Offline ready');
} else {
  console.warn('✗ Not offline ready yet');
}

// Test manually
// Chrome DevTools -> Application -> Service Workers -> Offline

9. ✅ Implement Fallback for Unsupported Browsers

// ✅ Good: graceful degradation
if (ServiceWorkerManager.isSupported()) {
  await ServiceWorkerManager.init({
    enabled: true
  });
} else {
  console.log('Service Worker not supported - using online-only mode');
  initializeOnlineOnlyMode();
}

10. ✅ Clean Up Old Caches

// ✅ Good: clear old caches on version change
const currentVersion = '2.0.0';
const storedVersion = localStorage.getItem('app-version');

if (storedVersion && storedVersion !== currentVersion) {
  await ServiceWorkerManager.clearCache();
  await ServiceWorkerManager.unregister();

  // Re-initialize with new version
  await ServiceWorkerManager.init({
    version: currentVersion,
    cacheName: `app-cache-${currentVersion}`
  });

  localStorage.setItem('app-version', currentVersion);
}

Summary

Key Features

Feature Supported Notes
Service Worker Registration Auto registration
Auto Caching Pattern-based
Caching Strategies network-first, cache-first, stale-while-revalidate
Push Notifications VAPID support
Offline Support Full offline mode
Auto Updates Configurable interval
Update Notifications User-friendly
Cache Management Manual control
Event System Lifecycle events
Debug Mode Development tools

When to Use ServiceWorkerManager

Use Case Use ServiceWorkerManager? Notes
Progressive Web App ✅ Yes Primary use case
Offline functionality ✅ Yes Full offline support
Push notifications ✅ Yes VAPID support
Performance optimization ✅ Yes Smart caching
Mobile web app ✅ Yes Better UX
Static site ⚠️ Partial Simple caching only
Admin dashboard ⚠️ Careful Sensitive data
Real-time app ⚠️ Careful Cache may be stale