Salta al contenuto principale

5 - Performance Budgets e Lighthouse CI in Pipeline

Come integrare Lighthouse CI nelle pipeline per monitorare automaticamente Core Web Vitals, bundle size e performance budgets.

Cosa ne pensi di questo articolo?

5 - Performance Budgets e Lighthouse CI in Pipeline
DevOps FrontendFoto:Antonio BatinićPexels

In Breve

Come integrare Lighthouse CI nelle pipeline per monitorare automaticamente Core Web Vitals, bundle size e performance budgets.

Introduzione: La Performance Come Requisito, Non Come Optional

Le performance web non sono un aspetto da ottimizzare "quando c'è tempo". Ogni millisecondo di ritardo nel caricamento si traduce in utenti persi: secondo Google, il 53% degli utenti mobile abbandona un sito se il caricamento supera i 3 secondi. I performance budgets trasformano le performance da obiettivo vago a vincolo misurabile e automatizzato nella pipeline CI/CD.

In questo articolo configureremo un sistema completo di monitoraggio delle performance: dalla definizione dei budget in angular.json all'integrazione di Lighthouse CI nella pipeline GitHub Actions, con soglie che bloccano il deploy se le metriche non rispettano gli standard.

Cosa Imparerai in Questo Articolo

  • Cosa sono i performance budgets e perchè sono importanti
  • Come configurare i budget in angular.json
  • Come installare e configurare Lighthouse CI (lhci)
  • La struttura del file lighthouserc.js
  • Come definire assertions e soglie di qualità
  • Come integrare Lighthouse CI con GitHub Actions
  • Come tracciare i punteggi nel tempo
  • Come monitorare la dimensione del bundle
  • Confronto con SpeedCurve e Calibre
  • Come far fallire la build in caso di regressioni

1. Cosa Sono i Performance Budgets

Un performance budget e un limite massimo predefinito per una o più metriche di performance. Quando il budget viene superato, la build fallisce, impedendo il deploy di codice che degrada l'esperienza utente. I budget più comuni sono:

Metriche di Performance Budget

Metrica Descrizione Budget Consigliato
Bundle size Dimensione totale dei file JavaScript e CSS JS iniziale < 300 KB (gzip)
LCP Largest Contentful Paint: tempo per il rendering dell'elemento più grande < 2.5 secondi
FID/INP Interaction to Next Paint: reattività dell'interfaccia < 200 ms
CLS Cumulative Layout Shift: stabilità visiva durante il caricamento < 0.1
FCP First Contentful Paint: primo contenuto visibile < 1.8 secondi
TTI Time to Interactive: quando la pagina diventa interattiva < 3.8 secondi

2. Performance Budgets in angular.json

Angular offre un sistema di budget integrato che controlla le dimensioni del bundle al momento della build. Se un budget viene superato, la build genera un warning o un errore.


{
  "projects": {
    "my-app": {
      "architect": {
        "build": {
          "configurations": {
            "production": {
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "400kb",
                  "maximumError": "500kb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "4kb",
                  "maximumError": "8kb"
                },
                {
                  "type": "anyScript",
                  "maximumWarning": "150kb",
                  "maximumError": "200kb"
                },
                {
                  "type": "any",
                  "maximumWarning": "300kb",
                  "maximumError": "500kb"
                }
              ]
            }
          }
        }
      }
    }
  }
}
      

Tipi di Budget Angular

Tipo Descrizione
initial Dimensione del bundle iniziale (main + polyfills + styles)
anyComponentStyle Dimensione di qualsiasi CSS di componente singolo
anyScript Dimensione di qualsiasi singolo file JavaScript
any Dimensione di qualsiasi singolo file nel bundle
allScript Dimensione totale di tutti i file JavaScript
all Dimensione totale di tutti i file nel bundle
bundle Dimensione di un bundle specifico (per nome)

3. Setup di Lighthouse CI

Lighthouse CI (LHCI) e lo strumento ufficiale di Google per automatizzare gli audit Lighthouse nelle pipeline CI/CD. Fornisce punteggi per performance, accessibilità, best practice e SEO.


# Installare Lighthouse CI
npm install -D @lhci/cli

# Oppure globalmente
npm install -g @lhci/cli

# Verificare l'installazione
lhci --version

# Eseguire un audit locale
lhci autorun
      

Configurazione lighthouserc.js

Il file lighthouserc.js nella root del progetto configura il comportamento di Lighthouse CI. Ecco una configurazione completa per un progetto Angular:


// lighthouserc.js
module.exports = {
  ci: {
    collect: {
      // Quante volte eseguire l'audit (per risultati stabili)
      numberOfRuns: 3,

      // URL da testare (dopo aver avviato il server)
      url: ['http://localhost:4200/'],

      // Avviare il server prima del test
      startServerCommand: 'npx ng serve --configuration=production',
      startServerReadyPattern: 'Angular Live Development Server',
      startServerReadyTimeout: 30000,

      // Impostazioni Chrome
      settings: {
        chromeFlags: '--no-sandbox --headless --disable-gpu',
        // Simulare una connessione 4G
        throttling: {
          rttMs: 150,
          throughputKbps: 1638.4,
          cpuSlowdownMultiplier: 4,
        },
      },
    },

    assert: {
      assertions: {
        // Performance
        'categories:performance': ['error', { minScore: 0.9 }],
        'first-contentful-paint': ['warn', { maxNumericValue: 2000 }],
        'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
        'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
        'total-blocking-time': ['warn', { maxNumericValue: 300 }],
        'speed-index': ['warn', { maxNumericValue: 3000 }],

        // Accessibilita
        'categories:accessibility': ['error', { minScore: 0.9 }],

        // Best Practice
        'categories:best-practices': ['warn', { minScore: 0.9 }],

        // SEO
        'categories:seo': ['error', { minScore: 0.9 }],

        // Audit specifici
        'uses-text-compression': 'error',
        'uses-responsive-images': 'warn',
        'render-blocking-resources': 'warn',
        'unused-javascript': 'warn',
      },
    },

    upload: {
      // Salvare i risultati come file temporanei
      target: 'temporary-public-storage',
    },
  },
};
      

Differenza tra Error e Warn nelle Assertions

Le assertions con livello error fanno fallire la build, impedendo il deploy. Le assertions con livello warn generano un avviso ma non bloccano la pipeline. Usa error per metriche critiche (LCP, CLS) e warn per metriche da monitorare (speed-index, risorse non ottimizzate).

4. Integrazione con GitHub Actions

Ecco il workflow completo per eseguire Lighthouse CI nella pipeline GitHub Actions:


# .github/workflows/lighthouse.yml
name: Lighthouse CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  lighthouse:
    name: Lighthouse Audit
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Build production
        run: npx ng build --configuration=production

      - name: Run Lighthouse CI
        uses: treosh/lighthouse-ci-action@v12
        with:
          configPath: './lighthouserc.js'
          uploadArtifacts: true
          temporaryPublicStorage: true

      - name: Upload Lighthouse reports
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: lighthouse-reports
          path: .lighthouseci/
          retention-days: 7
      

Configurazione Alternativa con Server Statico

Per risultati più affidabili, e preferibile servire la build di produzione con un server statico invece di usare ng serve:


// lighthouserc.js - con server statico
module.exports = {
  ci: {
    collect: {
      numberOfRuns: 5,
      url: ['http://localhost:8080/'],
      startServerCommand: 'npx http-server dist/my-app/browser -p 8080 -c-1',
      startServerReadyPattern: 'Available on',
      startServerReadyTimeout: 10000,
      settings: {
        chromeFlags: '--no-sandbox --headless --disable-gpu',
        preset: 'desktop',  // oppure 'perf' per mobile simulation
      },
    },
    assert: {
      preset: 'lighthouse:recommended',
      assertions: {
        'categories:performance': ['error', { minScore: 0.9, aggregationMethod: 'median-run' }],
        'categories:accessibility': ['error', { minScore: 0.9 }],
        'categories:best-practices': ['warn', { minScore: 0.85 }],
        'categories:seo': ['error', { minScore: 0.9 }],
      },
    },
    upload: {
      target: 'temporary-public-storage',
    },
  },
};
      

5. Tracciare i Punteggi nel Tempo

Per monitorare l'evoluzione delle performance, e utile salvare i punteggi storici. Lighthouse CI supporta un server dedicato per questo scopo, oppure possiamo usare un approccio più semplice con gli artifact di GitHub Actions:


  - name: Extract Lighthouse scores
    id: lh-scores
    run: |
      # Estrarre i punteggi dal report JSON
      REPORT=$(find .lighthouseci -name 'lhr-*.json' | head -1)
      PERF=$(jq '.categories.performance.score * 100' "$REPORT")
      A11Y=$(jq '.categories.accessibility.score * 100' "$REPORT")
      BP=$(jq '.categories["best-practices"].score * 100' "$REPORT")
      SEO=$(jq '.categories.seo.score * 100' "$REPORT")

      echo "performance=$PERF" >> "$GITHUB_OUTPUT"
      echo "accessibility=$A11Y" >> "$GITHUB_OUTPUT"
      echo "best-practices=$BP" >> "$GITHUB_OUTPUT"
      echo "seo=$SEO" >> "$GITHUB_OUTPUT"

  - name: Comment PR with scores
    if: github.event_name == 'pull_request'
    uses: actions/github-script@v7
    with:
      script: |
        const perf = '${{ steps.lh-scores.outputs.performance }}';
        const a11y = '${{ steps.lh-scores.outputs.accessibility }}';
        const bp = '${{ steps.lh-scores.outputs.best-practices }}';
        const seo = '${{ steps.lh-scores.outputs.seo }}';
        const body = `## Lighthouse Scores
        | Category | Score |
        |----------|-------|
        | Performance | ${perf}/100 |
        | Accessibility | ${a11y}/100 |
        | Best Practices | ${bp}/100 |
        | SEO | ${seo}/100 |`;
        github.rest.issues.createComment({
          issue_number: context.issue.number,
          owner: context.repo.owner,
          repo: context.repo.repo,
          body: body
        });
      

6. Monitoraggio della Dimensione del Bundle

Oltre a Lighthouse, e importante monitorare la dimensione del bundle nel tempo. Un aumento graduale e spesso impercettibile fino a quando non diventa un problema serio.


# Step per monitorare la dimensione del bundle
  - name: Analyze bundle size
    run: |
      # Calcolare la dimensione totale del bundle
      TOTAL=$(find dist/my-app/browser -name '*.js' -o -name '*.css' | \
        xargs wc -c | tail -1 | awk '{print $1}')
      TOTAL_KB=$((TOTAL / 1024))

      echo "Bundle totale: ${TOTAL_KB} KB"

      # Calcolare la dimensione gzippata
      GZIP_TOTAL=0
      for file in $(find dist/my-app/browser -name '*.js' -o -name '*.css'); do
        SIZE=$(gzip -c "$file" | wc -c)
        GZIP_TOTAL=$((GZIP_TOTAL + SIZE))
      done
      GZIP_KB=$((GZIP_TOTAL / 1024))

      echo "Bundle gzippato: ${GZIP_KB} KB"

      # Verificare il budget
      MAX_GZIP_KB=400
      if [ "$GZIP_KB" -gt "$MAX_GZIP_KB" ]; then
        echo "ERRORE: Bundle gzippato (${GZIP_KB} KB) supera il budget (${MAX_GZIP_KB} KB)"
        exit 1
      fi
      

Bundle Analyzer Visuale

Per capire cosa occupa spazio nel bundle, Angular fornisce un analizzatore visuale integrato:


# Generare le statistiche del bundle
npx ng build --configuration=production --stats-json

# Analizzare con webpack-bundle-analyzer
npx webpack-bundle-analyzer dist/my-app/browser/stats.json

# Alternativa: source-map-explorer per analisi più dettagliata
npx source-map-explorer dist/my-app/browser/main.*.js
      

7. Confronto con Strumenti Alternativi

Strumenti di Performance Monitoring

Strumento Tipo Costo Integrazione CI Ideale per
Lighthouse CI Open source Gratuito Nativa Tutti i progetti
SpeedCurve SaaS Da $20/mese API Monitoraggio continuo
Calibre SaaS Da $45/mese API Team enterprise
Bundlewatch Open source Gratuito GitHub App Solo bundle size
size-limit Open source Gratuito npm script Controllo rapido size

8. Far Fallire la Build su Regressioni

La configurazione più robusta combina i budget Angular con Lighthouse CI per creare una doppia barriera contro le regressioni di performance:


# Pipeline completa con performance gates
name: Performance Pipeline

on:
  pull_request:
    branches: [main]

jobs:
  build-check:
    name: Build and Budget Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci

      # Gate 1: Angular budget check (durante la build)
      - name: Build with budget check
        run: npx ng build --configuration=production
        # La build fallisce se i budget in angular.json sono superati

  lighthouse-check:
    name: Lighthouse Performance Audit
    runs-on: ubuntu-latest
    needs: build-check
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npx ng build --configuration=production

      # Gate 2: Lighthouse audit (metriche runtime)
      - name: Run Lighthouse CI
        uses: treosh/lighthouse-ci-action@v12
        with:
          configPath: './lighthouserc.js'
          uploadArtifacts: true
          temporaryPublicStorage: true
      

Strategia di Implementazione Graduale

  • Settimana 1: Esegui Lighthouse CI in modalità warn per raccogliere una baseline
  • Settimana 2: Imposta soglie basate sulla baseline (media - 5%)
  • Settimana 3: Passa le metriche critiche (LCP, CLS) a error
  • Settimana 4: Attiva le branch protection rules per richiedere il check Lighthouse
  • In corso: Stringi gradualmente le soglie man mano che il team ottimizza

Conclusione

In questo articolo abbiamo costruito un sistema completo di monitoraggio delle performance nella pipeline CI/CD. Abbiamo configurato i budget Angular per il controllo delle dimensioni del bundle, integrato Lighthouse CI per audit automatici a ogni Pull Request, e implementato il reporting dei punteggi direttamente nei commenti delle PR.

Il messaggio chiave e che le performance devono essere trattate come qualsiasi altro requisito del progetto: definite, misurate e verificate automaticamente. Con i budget e Lighthouse CI nella pipeline, ogni regressione viene catturata prima di raggiungere la produzione.

Nell'ultimo articolo della serie affronteremo il monitoraggio e alerting per applicazioni web: error tracking con Sentry, real user monitoring, e strategie per mantenere la qualità anche dopo il deploy.

Domande frequenti

Cosa sono i performance budget?

I performance budget sono limiti massimi predefiniti per una o più metriche di performance. Quando il budget viene superato, la build fallisce, impedendo il deploy di codice che degrada l'esperienza utente.

Come funziona Angular per controllare le dimensioni del bundle?

Angular offre un sistema di budget integrato che controlla le dimensioni del bundle al momento della build. Se un budget viene superato, la build genera un warning o un errore.

Qual è lo scopo di Lighthouse CI nella pipeline CI/CD?

Lighthouse CI (LHCI) è uno strumento ufficiale di Google per automatizzare gli audit Lighthouse nelle pipeline CI/CD. Fornisce punteggi per performance, accessibilità, best practice e SEO.

Come posso monitorare l'evoluzione delle performance del mio sito web?

Puoi salvare i punteggi storici utilizzando un server dedicato di Lighthouse CI o un approccio più semplice con gli artifact di GitHub Actions.

Fonti e approfondimenti

Prova Questi Strumenti

Strumenti gratuiti correlati a questo argomento.

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti