Sviluppo web

Lighthouse CI con budget: le assertions che bloccano il merge

`lighthouserc.json` con `numberOfRuns`, asserzioni su LCP, CLS e TBT e budget sui byte: la configurazione che ferma il merge quando il sito peggiora.

In sintesi

  • `lhci autorun` raccoglie, confronta con le soglie e pubblica: un'asserzione `error` fa fallire il job, `warn` no.
  • `numberOfRuns: 3` tiene la mediana e riduce la varianza del runner; le soglie 2.500 ms, 0,1 e 200 ms sono quelle di web.dev.
  • I budget sui byte (`resource-summary`) sono più stabili dei punteggi perché non dipendono dalla velocità della macchina.

Risposta breve: installa @lhci/cli, descrivi URL e soglie in lighthouserc.json e lancia lhci autorun in CI. Se un'asserzione error non passa, il job si ferma e il merge non entra.

Installare e lanciare una volta a mano

npm i -D @lhci/[email protected]
npx lhci autorun --collect.url=http://localhost:3000/

autorun fa tre passi: collect avvia Chrome headless e salva i report, assert confronta i numeri con le soglie, upload pubblica l'esito. Il primo giro serve a vedere i numeri veri prima di scegliere le soglie.

Il file di configurazione

{
  "ci": {
    "collect": { "url": ["http://localhost:3000/"], "numberOfRuns": 3 },
    "assert": {
      "assertions": {
        "categories:performance": ["error", { "minScore": 0.9 }],
        "largest-contentful-paint": ["error", { "maxNumericValue": 2500 }],
        "cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }],
        "total-blocking-time": ["error", { "maxNumericValue": 200 }]
      }
    },
    "upload": { "target": "temporary-public-storage" }
  }
}

numberOfRuns: 3 esegue Lighthouse tre volte e tiene la mediana: è il rimedio alla varianza di un runner condiviso. Le soglie 2.500 ms, 0,1 e 200 ms sono quelle pubblicate da web.dev per LCP, CLS e TBT.

error, warn e il resto

Un'asserzione error fa terminare il job, warn stampa e prosegue. Comincia con warn su un progetto già in produzione e passa a error dopo aver portato i numeri sotto soglia: un budget che blocca il team dal primo giorno viene disattivato in una settimana.

Budget in byte, non solo punteggi

{
  "ci": {
    "assert": {
      "assertions": {
        "resource-summary:script:size": ["error", { "maxNumericValue": 180000 }],
        "resource-summary:total:size": ["error", { "maxNumericValue": 600000 }]
      }
    }
  }
}

Le asserzioni resource-summary contano i byte trasferiti per tipo di risorsa. Sono più stabili dei punteggi, perché non dipendono dalla velocità del runner: un budget sui byte cambia quando cambia il codice.

Limite dichiarato

Lighthouse CI misura in laboratorio con throttling simulato: non sostituisce i dati di campo di CrUX, che arrivano dagli utenti reali. Un punteggio 100 non garantisce un LCP sotto 2,5 s su un telefono lento.

Dove continuare

Nel catalogo trovi la card con metrica, il grafico a ciambella e i blocchi della categoria chart. Per il resto leggi le soglie di Lighthouse CI spiegate, la guida a PerformanceObserver e il confronto analytics Vercel o self-hosted.

Domande frequenti

Lighthouse CI è lo stesso strumento di Lighthouse?

Sì. @lhci/cli orchestra Lighthouse: collect avvia le esecuzioni, assert confronta i risultati, upload conserva i report. Il motore di misura è lo stesso.

Quante esecuzioni servono per un risultato stabile?

Tre è il minimo pratico, cinque su un runner molto variabile. Lighthouse CI usa la mediana delle esecuzioni, quindi un singolo valore anomalo non decide l'esito.

Devo ospitare un server per i report?

No. Con upload target temporary-public-storage i report restano disponibili per pochi giorni su uno spazio pubblico. Per la cronologia serve un server LHCI, che è un progetto a parte.

Posso bloccare solo le regressioni, non i valori assoluti?

Sì, è la configurazione più utile su un progetto già lento: confronti la build corrente con la precedente e fissi una tolleranza. Le asserzioni su valori assoluti servono dopo aver portato i numeri sotto soglia.

Lighthouse CI misura anche su mobile reale?

No. Emula un telefono con CPU e rete rallentate dentro Chrome headless: utile per confrontare build, non per stimare l'esperienza su un dispositivo specifico.