# A site performance budget you can actually enforce

A performance budget caps bytes and milliseconds per deploy. Our home page weighs 327,750 bytes in 23 requests, 196,252 of them fonts: how to set it.

> Page: https://ui.eneawork.it/blog/performance-budget-sito
> Markdown: https://ui.eneawork.it/blog/performance-budget-sito.md

*2026-11-01*

Un performance budget è un tetto di byte e di millisecondi che ogni deploy deve rispettare: la home del nostro sito carica 327.750 byte in 23 richieste, e 196.252 byte sono font. Il budget che ne deriva è 400 KB in totale, 200 KB di font, 100 KB di JavaScript, 30 KB di CSS e 40 KB di immagini.

Build di produzione del repository, servita da node backend/server.js su localhost:3100 e misurata cinque volte in Chrome 155 headless con puppeteer, rete Slow 4G simulata (1,6 Mbps, 150 ms di RTT) e CPU rallentata 4 volte. Mediana: 327.748 byte in 23 richieste, LCP 2.856 ms, TTFB 167 ms, tre long task per 486 ms. Comando: node scripts/perf-lab.js http://localhost:3100/ 5. La ripartizione per estensione viene da un caricamento a freddo della stessa pagina: font 196.252 byte in 6 file, JavaScript 90.897 byte, CSS 22.486 byte in 5 fogli, HTML 12.434 byte, immagini 3.717 byte. La pagina articolo misura 452.505 byte in 28 richieste. 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. Soglie: web.dev, CC BY 4.0.

## Dove finiscono i byte

## Anche il tempo ha un tetto

I font sono il 60% del totale: sei file per 196.252 byte, e ogni peso è un download che il browser deve completare prima di mostrare il testo. Il margine positivo sul totale non compensa uno sforamento per tipo: se un tipo sfonda il suo tetto il deploy si blocca lo stesso, ed è il comportamento che vuoi.

## Il budget che si applica da solo

{ "performance": { "budget": [ { "resourceType": "total", "budget": 400 }, { "resourceType": "stylesheet", "budget": 220 }, { "resourceType": "script", "budget": 60 }, { "resourceType": "font", "budget": 50 }, { "resourceType": "image", "budget": 40 } ], "timings": [ { "metric": "largest-contentful-paint", "budget": 2500 }, { "metric": "cumulative-layout-shift", "budget": 0.1 } ] } }

Le cifre sono in kilobyte e descrivono il trasferimento, non il peso decompresso. Il file si passa a Lighthouse con --budget-path:

npx lighthouse http://localhost:3100/ --budget-path=budget.json \ --output=json --output-path=./lh.json --chrome-flags="--headless"

Lighthouse elenca le voci fuori budget nella categoria budgets. Per far fallire la pipeline serve Lighthouse CI, che con le stesse soglie in assert restituisce un exit code diverso da zero.

## Cosa tagliare per primo

## Il limite da dichiarare

Il budget misura il laboratorio, non i tuoi utenti: 2.672 ms di LCP su Slow 4G simulato non sono il 75° percentile di campo. I byte restano validi perché non dipendono dalla rete; le soglie di tempo vanno confrontate con i dati reali, e su una connessione peggiore il long task da 492 ms può raddoppiare.

## Dove continuare

Il catalogo EneUI indicizza 111.985 componenti, per esempio sparkles, e il blocco banner-01: una pagina con tre di questi blocchi aggiunge immagini e CSS al budget. Per le soglie leggi cosa sono i Core Web Vitals, per il costo degli script JavaScript di terze parti, per la cache cache e CDN e per il confronto tra architetture framework frontend a confronto.

## FAQ

### Quanto deve pesare una pagina?

Non esiste un numero universale: si parte dal peso misurato e si fissa un tetto appena sopra, poi lo si abbassa. La nostra home parte da 327.750 byte e il budget è 400.000.

### Meglio un budget in byte o in millisecondi?

Servono entrambi. I byte sono deterministici e si controllano in CI; i millisecondi dipendono da rete e CPU, quindi vanno letti insieme ai dati di campo.

### Il budget si applica per pagina o per tipo di risorsa?

Per tipo di risorsa. Un totale rispettato può nascondere un CSS enorme compensato da poche immagini, e il CSS blocca il rendering.

### Come faccio fallire la build?

Con Lighthouse CI e le soglie in assert. Lighthouse da solo riporta le voci fuori budget, Lighthouse CI trasforma l'esito in un exit code.

### Il budget va aggiornato?

Sì, quando una feature nuova aggiunge peso in modo deliberato. Si alza il tetto nel commit che spiega perché, non in silenzio dopo il fallimento.
