# Caching with a service worker: what to cache and what to skip

A service worker serves assets from cache and leaves HTML to the network. This site has none today: /sw.js returns 404 and caching lives in the headers.

> Page: https://ui.eneawork.it/blog/service-worker-cache
> Markdown: https://ui.eneawork.it/blog/service-worker-cache.md

*2026-11-01*

Un service worker mette in cache gli asset che non cambiano e lascia l'HTML alla rete, così la seconda visita non riscarica 65 file. Oggi questo sito non ne ha uno: /sw.js risponde 404 e la cache vive solo negli header HTTP.

Il 1 novembre 2026 https://ui.eneawork.it/sw.js e /service-worker.js rispondono 404, mentre /manifest.webmanifest risponde 200 con 677 byte. Il build dello stesso giorno produce 65 file statici, 48 JavaScript e 17 CSS, per 672.318 byte e 212.752 byte in gzip: è il tetto di un precache completo. Codici letti con curl -sS -o /dev/null -w "%{http_code}"; byte misurati da client/dist/assets. Il catalogo EneUI misura 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, letti da /api/stats il 1 novembre 2026. Riferimento: MDN, licenza CC BY-SA 2.5.

## Quattro risorse, quattro strategie

## Il worker minimo

self.addEventListener("install", (event) => { event.waitUntil( caches.open("static-v1").then((cache) => cache.addAll(["/", "/manifest.webmanifest"]), ), ); }); self.addEventListener("fetch", (event) => { const url = new URL(event.request.url); if (url.pathname.startsWith("/api/")) return; event.respondWith( caches.match(event.request).then((hit) => hit || fetch(event.request)), ); });

L'install apre una cache con un nome versionato e ci mette i file stabili; il fetch risponde dalla cache e passa alla rete solo quando manca una corrispondenza. Le richieste a /api/ escono subito, così i dati non diventano vecchi.

## Il comando

curl -sS -o /dev/null -w "%{http_code}\n" https://ui.eneawork.it/sw.js

Il comando stampa 404 finché il file non esiste: è il controllo da fare dopo il deploy, perché un worker registrato una volta resta attivo anche se il file sparisce dal server.

## La limitazione

Oggi la cache è tutta negli header HTTP e la misura descrive il tetto di un precache, non un risparmio ottenuto. Un worker mal configurato serve HTML vecchio, e per disattivarlo devi pubblicare un file che si disiscrive: non basta cancellarlo dal server.

## Dove continuare

Nel catalogo EneUI: 111.985 componenti, 1.556 blocchi e il record sidebar, un componente che non cambia tra una visita e l'altra. Le guide: Cache-Control e immutable e il code splitting per route; il confronto Brotli contro gzip dice quanto pesa davvero ciò che metti in cache.

## FAQ

### Serve un service worker per avere una cache?

No. La cache HTTP con Cache-Control copre già HTML e asset e non richiede codice. Il service worker aggiunge il controllo offline e la cache programmabile, ma introduce anche un punto in cui puoi servire contenuto vecchio.

### Perché non mettere tutto in cache-first?

Perché l'HTML e le API cambiano. Con cache-first su tutto il primo contenuto servito resta finché non cambi la versione della cache, anche dopo un deploy.

### Come si aggiorna un service worker?

Il browser scarica il file a ogni visita e attiva la nuova versione quando tutte le schede del vecchio worker si chiudono. Cambia il nome della cache nell'install per non riusare i file vecchi.

### Il service worker peggiora la prima visita?

Sì, un precache completo scarica subito tutti i file elencati. Limitalo agli asset critici e lascia il resto alla cache on demand.

### Come lo rimuovo se qualcosa va storto?

Pubblica un worker che chiama self.registration.unregister() e cancella le cache, poi lascialo in produzione per almeno un ciclo di visite. Cancellare il file dal server non basta.
