Now.js Framework Documentation
ServiceWorkerManager - Service Worker Management
ServiceWorkerManager - Service Worker Management
Documentation for ServiceWorkerManager, a service worker management system for offline functionality and push notifications.
📋 Table of Contents
- Overview
- Installation and Import
- Basic Usage
- Cache Management
- Caching Strategies
- Push Notifications
- Offline Support
- Updates and Lifecycle
- Configuration
- Usage Examples
- API Reference
- 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:
- network-first: Try network first, fallback to cache
- cache-first: Use cache first, fallback to network
- 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(): booleanCache 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(): booleanStatus
// 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 -> Offline9. ✅ 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 |