DEV Community

Weather Clock Dash
Weather Clock Dash

Posted on

PWAs in Firefox: What Works, What Doesn't, and Service Worker Debugging

Progressive Web Apps (PWAs) in Firefox have a complicated history. Firefox removed PWA installation support on desktop in 2021 (it was barely used), then started re-introducing it. Here's the current state and what actually works.

Current PWA Support in Firefox (2024)

Mobile (Android): Full PWA support. "Add to home screen" works, standalone mode works, service workers, push notifications — full PWA.

Desktop (Windows/macOS/Linux): Firefox removed the "install PWA" button in 2021. The feature is being worked on again as of 2023-2024.

The workaround: On desktop Firefox, you can't install PWAs as standalone apps from Firefox's UI. You can:

  1. Use a workaround extension like "PWAsForFirefox"
  2. Use Firefox Nightly, which has reinstated PWA installation as an experiment
  3. Use the site in a regular Firefox window (service workers, offline cache, all the features still work — just without the standalone app window)

This is a real limitation compared to Chrome on desktop.

What Still Works in Firefox's PWA Implementation

Even without installable PWA on Firefox desktop, the underlying technologies work:

Service Workers: Fully supported. Offline caching, background sync, push notifications infrastructure — all work.

Web App Manifest: Firefox reads manifest.json for metadata, icons, and theme color. In mobile Firefox, this drives the "Add to home screen" feature.

Push Notifications: Web Push API works in Firefox desktop and mobile. Sites can send push notifications with user permission.

Background Sync: Service worker background sync events work in Firefox.

IndexedDB and Cache API: Full support for offline storage.

So if you're building a PWA: the app logic works perfectly in Firefox. The missing piece is the "install to desktop" launcher.

Testing Your PWA in Firefox

Check service worker registration:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(reg => {
      console.log('SW registered:', reg.scope);
    })
    .catch(err => {
      console.error('SW registration failed:', err);
    });
}
Enter fullscreen mode Exit fullscreen mode

DevTools → Application panel (called "Storage" in Firefox):
Firefox doesn't have Chrome's "Application" tab. Instead:

  • Service workers: about:serviceworkers
  • Cache API: DevTools → Storage → Cache Storage
  • IndexedDB: DevTools → Storage → IndexedDB
  • Manifest: not shown directly in DevTools (check about:debugging)

Check PWA installability:
Firefox DevTools doesn't have Chrome's "Lighthouse" or "Install" button. To audit PWA installability:

  1. Use Lighthouse via Chrome
  2. Or use the PWA Builder tool online
  3. Or check manifest manually

Manifest.json Best Practices

A web app manifest that Firefox reads correctly:

{
  "name": "My App",
  "short_name": "App",
  "description": "What it does",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#2563eb",
  "icons": [
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "maskable any"
    },
    {
      "src": "/icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable any"
    }
  ],
  "screenshots": [
    {
      "src": "/screenshots/desktop.png",
      "sizes": "1280x720",
      "type": "image/png",
      "form_factor": "wide"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Link in HTML:

<link rel="manifest" href="/manifest.json">
<meta name="theme-color" content="#2563eb">
Enter fullscreen mode Exit fullscreen mode

Service Worker Debugging in Firefox

about:serviceworkers: Shows all registered service workers globally. You can unregister them here.

DevTools for SW debugging:
In DevTools → Debugger, service workers appear in the Sources pane under "Workers".

Simulating offline:
Firefox DevTools → Network → check "Work Offline" to test offline behavior (simulates no network connection).

Service worker update behavior:

// service-worker.js
const CACHE = 'v2'; // Increment to force update

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE).then(cache => 
      cache.addAll(['/index.html', '/app.js', '/styles.css'])
    )
  );
  // Take control immediately (skip waiting)
  self.skipWaiting();
});

self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(keys => 
      Promise.all(
        keys.filter(key => key !== CACHE)
          .map(key => caches.delete(key))
      )
    )
  );
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(cached => cached || fetch(event.request))
  );
});
Enter fullscreen mode Exit fullscreen mode

PWAsForFirefox Extension

For desktop Firefox users who want actual PWA installation:

PWAsForFirefox extension on AMO provides Firefox PWA installation:

  • Installs a native handler
  • PWAs show as standalone app windows
  • Integrates with system app lists
  • Open source

The setup is more involved than Chrome's one-click install, but it works.

Push Notifications in Firefox

Web Push works the same in Firefox as Chrome:

// Request notification permission
const permission = await Notification.requestPermission();
if (permission !== 'granted') return;

// Get push subscription
const registration = await navigator.serviceWorker.ready;
const sub = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: urlBase64ToUint8Array(PUBLIC_KEY)
});

// Send subscription to your backend
await fetch('/api/subscribe', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(sub)
});
Enter fullscreen mode Exit fullscreen mode

Firefox vs Chrome push: Firefox uses Mozilla's push server (autopush.mozilla.com) by default. Chrome uses Google's. Both use the Web Push Protocol (RFC 8030), so the backend code is the same.

IndexedDB for PWA Storage

Firefox has full IndexedDB support:

const request = indexedDB.open('myDB', 1);

request.onupgradeneeded = (event) => {
  const db = event.target.result;
  const store = db.createObjectStore('items', { keyPath: 'id' });
  store.createIndex('name', 'name', { unique: false });
};

request.onsuccess = (event) => {
  const db = event.target.result;
  // Use the db
};
Enter fullscreen mode Exit fullscreen mode

Firefox DevTools Storage panel → IndexedDB shows the database, object stores, and individual records. You can inspect, edit, and delete records here.

The Firefox PWA Situation: Summary

What works:

  • Service workers (offline, caching, background sync)
  • Web Push notifications
  • IndexedDB, Cache API
  • Web App Manifest (for mobile "add to home screen")
  • PWA features on Android Firefox

What doesn't work natively on desktop Firefox:

  • Install PWA as standalone desktop app
  • The "install" button in the address bar

Workarounds for desktop:

  • PWAsForFirefox extension
  • Firefox Nightly (has experimental PWA install)
  • Just bookmark it and use in browser window (all features still work)

If you're building PWAs and need to support Firefox: the app will work, just not install to the desktop without the extension. For most PWAs, this is acceptable — they work correctly in the Firefox browser window.

Top comments (0)