惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
小众软件
小众软件
博客园 - 叶小钗
宝玉的分享
宝玉的分享
博客园_首页
Hugging Face - Blog
Hugging Face - Blog
人人都是产品经理
人人都是产品经理
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
SegmentFault 最新的问题
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
Google DeepMind News
Google DeepMind News
U
Unit 42
F
Fortinet All Blogs
IT之家
IT之家
Y
Y Combinator Blog
Martin Fowler
Martin Fowler
T
The Blog of Author Tim Ferriss
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The GitHub Blog
The GitHub Blog
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
酷 壳 – CoolShell
酷 壳 – CoolShell

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Making a Firefox Extension Work Offline — Service Workers...
Weather Cloc · 2026-05-04 · via DEV Community

Weather Clock Dash

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.