DEV Community

Weather Clock Dash
Weather Clock Dash

Posted on

Making a Firefox Extension Work Offline — Service Workers vs. Cache API

Making a Firefox Extension Work Offline — Service Workers vs. Cache API

A common question when building browser extensions: how do you handle offline or spotty network conditions? Here is what I learned building the Weather & Clock Dashboard.

The Problem

The extension fetches weather data from an external API. If the user opens a new tab with no internet connection, they should see the last known weather, not an error.

Option 1: Service Workers

Service workers can intercept network requests and serve cached responses. But in MV3 Firefox extensions, service workers have limitations — they are not persistent and can be terminated.

// manifest.json
"background": { "service_worker": "background.js" }
Enter fullscreen mode Exit fullscreen mode

Option 2: browser.storage.local (What I Used)

For an extension that just needs to cache the last API response, browser.storage.local is simpler and more reliable than a service worker:

async function getWeather(city) {
  const CACHE_KEY = 'weather_cache';
  const CACHE_TTL = 10 * 60 * 1000; // 10 minutes

  // Check cache first
  const { weather_cache } = await browser.storage.local.get(CACHE_KEY);
  if (weather_cache && Date.now() - weather_cache.timestamp < CACHE_TTL) {
    return weather_cache.data;
  }

  try {
    const resp = await fetch(`https://wttr.in/${city}?format=j1`);
    const data = await resp.json();

    // Store in cache
    await browser.storage.local.set({
      [CACHE_KEY]: { data, timestamp: Date.now() }
    });

    return data;
  } catch (err) {
    // Return stale cache if available
    return weather_cache?.data || null;
  }
}
Enter fullscreen mode Exit fullscreen mode

Why This Works Better

  1. Survives offline — returns last good data even without network
  2. Survives extension reload — data persists across browser sessions
  3. No service worker complexity — simpler mental model
  4. Reduces API calls — cached for 10 minutes

Showing Stale Data

When showing cached data, indicate it to the user:

const isStale = Date.now() - cache.timestamp > CACHE_TTL;
if (isStale) {
  showWeather(cache.data);
  weatherEl.classList.add('stale'); // gray out or add "last updated" label
}
Enter fullscreen mode Exit fullscreen mode

This pattern — cache-first with stale fallback — is robust for any extension that fetches external data.

Top comments (0)