Wer mehrere unabhängige Websites gleichzeitig betreibt, ändert an jeder von ihnen laufend etwas: ein neues npm-Paket, ein zusätzliches Analyse-Skript, ein neues Bildformat. Jede dieser Änderungen kann die Ladezeit einer Seite verschlechtern, ohne dass es beim Testen im eigenen Browser auffällt. Ohne eine automatisierte Prüfung zeigt sich eine solche Regression oft erst Wochen später, entweder über eine sinkende Position bei Google oder über den Bericht Core Web Vitals in der Google Search Console, dem kostenlosen Werkzeug, mit dem Google Website-Betreibern zeigt, wie ihre Seiten in der echten Suche abschneiden.
Core Web Vitals sind drei von Google dokumentierte Messwerte, die als Rankingfaktor in die Google-Suche einfließen. Largest Contentful Paint (LCP) misst, wie schnell der größte sichtbare Inhalt einer Seite lädt. Interaction to Next Paint (INP) misst, wie schnell eine Seite auf eine Nutzereingabe reagiert, und hat seit dem 12. März 2024 die vorherige Kennzahl First Input Delay als offizielle Core-Web-Vital-Metrik abgelöst. Cumulative Layout Shift (CLS) misst, wie stark sich Inhalte nach dem Laden noch verschieben. Lighthouse, Googles quelloffenes Prüfmodul, berechnet alle drei Werte in einer simulierten Laborumgebung und liefert dieselben Ergebnisse, die auch in Chrome DevTools erscheinen und die PageSpeed Insights seit November 2018 als eigene Analysegrundlage übernommen hat.
Lighthouse CI baut auf demselben Prüfmodul auf, ist aber ein eigenständiges Werkzeug: das npm-Paket @lhci/cli, gepflegt im GitHub-Repository GoogleChrome/lighthouse-ci unter der Apache-2.0-Lizenz. Es führt Lighthouse automatisiert in einer Build-Pipeline aus, vergleicht das Ergebnis gegen festgelegte Schwellenwerte und lässt den Workflow nur bei einer echten Regression fehlschlagen. Für ein Portfolio aus mehreren eigenständigen Websites lässt sich dieselbe Konfiguration gegen jede einzelne URL ausführen, entweder direkt über den Befehl lhci autorun oder über die GitHub Action treosh/lighthouse-ci-action.
Systemvoraussetzungen
Eine automatisierte Core-Web-Vitals-Kontrolle braucht wenige, aber genau passende Bausteine. Die folgende Tabelle nennt die aktuellen Anforderungen und wofür jeder Baustein steht.
| Komponente | Version oder Anforderung | Zweck |
|---|---|---|
| Node.js | aktuelle LTS-Version | Laufzeitumgebung, in der @lhci/cli und der Website-Build laufen |
@lhci/cli | aktuell Version 0.15.1, gepflegt im Repository GoogleChrome/lighthouse-ci | Kommandozeilenwerkzeug mit den Befehlen collect, assert und upload |
| Chrome oder Chromium | aktuelle stabile Version, headless ausführbar | Browser, in dem Lighthouse jede Seite tatsächlich lädt und misst |
lighthouserc.js oder lighthouserc.json | im Projekt-Root oder über die Option --config angegeben | Enthält die URL-Liste, die Anzahl der Durchläufe und die assert-Regeln |
| GitHub-Actions-Runner | zum Beispiel ubuntu-latest | Umgebung, die den Workflow und lhci autorun ausführt |
| Speicherziel für Berichte | temporary-public-storage oder ein selbst betriebener LHCI-Server (@lhci/server) | Bestimmt, wohin jeder Lighthouse-Bericht nach dem Lauf hochgeladen wird |
Systemarchitektur
Eine Website mit automatisierter Core-Web-Vitals-Kontrolle hat drei Bausteine, die bei jedem Pull Request zusammenspielen: den Build oder Vorschauserver, der die zu prüfende Version bereitstellt, Lighthouse CI, das gegen jede konfigurierte URL misst, und die assert-Regeln, die über Erfolg oder Abbruch entscheiden. Das folgende Schaubild zeigt diesen Ablauf von der Codeänderung bis zum vergleichbaren Bericht.
flowchart TD
A[Neuer Commit oder Pull Request entsteht] --> B[GitHub Actions startet den Workflow]
B --> C[Runner baut die Website oder startet den Vorschauserver]
C --> D[lhci autorun ruft Lighthouse fuer jede konfigurierte URL auf]
D --> E[Lighthouse fuehrt mehrere Durchlaeufe je Seite aus]
E --> F[Median aus den Durchlaeufen bildet den Referenzwert]
F --> G[assert-Regeln aus lighthouserc.js pruefen jeden Schwellenwert]
G --> H{Liegt ein Wert ausserhalb des Budgets}
H -->|Nein| I[Workflow meldet Erfolg und laedt den Bericht hoch]
H -->|Ja| J[Workflow schlaegt fehl und blockiert den Merge]
I --> K[Bericht liegt im temporaeren Speicher oder auf dem LHCI-Server]
J --> K
K --> L[Team vergleicht den neuen Bericht mit dem vorherigen Lauf]
Ein Commit oder ein Pull Request löst den Workflow aus. Der Runner baut die betroffene Website oder startet einen Vorschauserver und ruft anschließend lhci autorun mit der in lighthouserc.js hinterlegten URL-Liste auf. Für jede URL führt Lighthouse mehrere Durchläufe hintereinander aus, weil ein einzelner Durchlauf durch schwankende Netzwerklatenz oder Auslastung des Runners um mehrere Punkte streuen kann. Aus diesen Durchläufen bildet Lighthouse CI den Median und prüft ihn gegen die assert-Regeln. Eine Regel mit dem Schweregrad error lässt den gesamten Workflow fehlschlagen, eine Regel mit warn meldet nur eine Warnung und lässt den Build durchlaufen. Erst danach lädt Lighthouse CI den vollständigen Bericht hoch, entweder in den temporären öffentlichen Speicher von Google oder auf einen selbst betriebenen LHCI-Server, der Berichte dauerhaft aufbewahrt und einen Vergleich zwischen zwei Commits erlaubt.
Schritt-für-Schritt-Umsetzung
Lighthouserc-Konfiguration mit Schwellenwerten aufsetzen
Die Datei lighthouserc.js liegt im Projekt-Root und exportiert ein Konfigurationsobjekt mit drei Bereichen: collect für die zu prüfenden URLs und die Anzahl der Durchläufe, assert für die Schwellenwerte, und upload für das Speicherziel der Berichte.
module.exports = {
ci: {
collect: {
url: [
'https://www.beispiel-portfolio.de/',
'https://www.beispiel-portfolio.de/artikel/beispiel-artikel',
],
numberOfRuns: 5,
},
assert: {
preset: 'lighthouse:recommended',
assertions: {
'categories:performance': ['error', { minScore: 0.85 }],
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
'total-blocking-time': ['warn', { maxNumericValue: 300 }],
'offscreen-images': 'off',
},
},
upload: {
target: 'temporary-public-storage',
},
},
};
Der Wert numberOfRuns legt fest, wie oft Lighthouse dieselbe Seite hintereinander misst, bevor Lighthouse CI den Median bildet. Der Preset-Wert lighthouse:recommended übernimmt sinnvolle Standardregeln für alle Lighthouse-Kategorien und lässt sich über die eigenen assertions gezielt verschärfen oder abschwächen. Jede Regel folgt demselben Muster aus Audit-Kennung und einem Array aus Schweregrad und Optionsobjekt: categories:performance mit minScore prüft die Gesamtpunktzahl, largest-contentful-paint und cumulative-layout-shift mit maxNumericValue prüfen die konkreten Millisekunden- oder Score-Werte der einzelnen Core Web Vitals. Interaction to Next Paint lässt sich in dieser Konfiguration bewusst nicht direkt prüfen: Der Wert setzt echte Nutzerinteraktionen voraus, die ein automatisierter Lighthouse-Lauf ohne Publikum nicht erzeugt. Total Blocking Time dient stattdessen als Laborersatzwert, der laut Googles eigener Dokumentation stark mit einer schlechten Interaction to Next Paint korreliert, ohne sie zu ersetzen. Ein Audit lässt sich mit dem Wert off vollständig abschalten, etwa wenn ein Team eine bestimmte Regel bewusst nicht durchsetzen will.
GitHub-Actions-Workflow für mehrere Websites schreiben
Für ein Portfolio aus mehreren unabhängigen Websites lässt sich derselbe Prüflauf in einem gemeinsamen Workflow gegen alle betroffenen Seiten ausführen. Die GitHub Action treosh/lighthouse-ci-action kapselt lhci autorun und übernimmt die URL-Liste entweder aus ihren eigenen Eingaben oder aus der lighthouserc.js.
name: Lighthouse CI
on:
pull_request:
branches: [main]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Website A bauen
run: npm ci && npm run build
working-directory: ./website-a
- name: Website B bauen
run: npm ci && npm run build
working-directory: ./website-b
- name: Lighthouse CI gegen beide Websites ausfuehren
uses: treosh/lighthouse-ci-action@v12
with:
configPath: './lighthouserc.js'
urls: |
https://preview-a.beispiel-portfolio.de/
https://preview-b.beispiel-portfolio.de/
uploadArtifacts: true
temporaryPublicStorage: true
Der Eingabewert urls überschreibt die in lighthouserc.js hinterlegte Liste und nimmt beliebig viele Adressen entgegen, eine pro Zeile. Damit lässt sich derselbe Workflow für ein wachsendes Portfolio erweitern, indem einfach weitere Build-Schritte und weitere Zeilen unter urls dazukommen, ohne die assert-Regeln neu zu schreiben. Betreibt eine Organisation jede Website in einem eigenen Repository statt in einem gemeinsamen Monorepo, lässt sich dieselbe Job-Definition als wiederverwendbarer Workflow über workflow_call zentral pflegen, sodass jedes Website-Repository nur noch seine eigene URL-Liste als Eingabe übergibt.
Berichte vergleichen und Regressionen einordnen
Mit uploadArtifacts und temporaryPublicStorage lädt die Action nach jedem Lauf einen vollständigen HTML-Bericht in Googles temporären öffentlichen Speicher hoch und verlinkt ihn direkt im Pull Request. Dieser Speicher ist bewusst kurzlebig: Laut der Dokumentation von treosh/lighthouse-ci-action werden dort abgelegte Berichte nach sieben Tagen automatisch wieder gelöscht, was für den schnellen Blick auf einen einzelnen Pull Request reicht, aber keinen Verlauf über Monate ermöglicht. Wer Ergebnisse dauerhaft vergleichen will, betreibt stattdessen einen eigenen LHCI-Server über das Paket @lhci/server und trägt dessen Adresse als serverBaseUrl samt Zugriffstoken in die Konfiguration ein. Ein solcher Server speichert jeden Lauf mit Commit-Hash und Zeitstempel und zeigt in einer eigenen Oberfläche, wie sich Largest Contentful Paint, Cumulative Layout Shift und Total Blocking Time einer Seite über die Zeit entwickelt haben, statt nur den letzten Pull Request gegen den vorherigen zu stellen.
Häufige Fehlerquellen
- numberOfRuns fehlt oder steht auf 1. Ein einzelner Lighthouse-Durchlauf kann laut Googles eigener Variabilitätsdokumentation allein durch Netzwerk- und Systemschwankungen um mehrere Punkte abweichen, wodurch derselbe Commit im Workflow einmal besteht und beim nächsten Versuch fehlschlägt. Fix: numberOfRuns auf mindestens 5 setzen, damit Lighthouse CI den Median verwendet.
- Eine assert-Regel zielt auf interaction-to-next-paint als Lighthouse-Audit. Diese Kennung existiert in einem Lighthouse-Laborbericht nicht, weil Interaction to Next Paint echte Nutzerinteraktionen voraussetzt. Fix: total-blocking-time als Laborersatzwert prüfen und die tatsächliche Interaction to Next Paint separat über Nutzerdaten beobachten, etwa über die Google Search Console.
- Lighthouse CI läuft gegen die Produktions-URL statt gegen eine isolierte Vorschau. Werbe-Skripte, Tracking-Cookies und wechselnde Live-Inhalte auf der Produktionsseite erzeugen zusätzliches Rauschen und machen Ergebnisse zwischen zwei Läufen schwerer vergleichbar. Fix: gegen einen dedizierten Vorschau-Build oder eine Staging-Umgebung ohne Drittanbieter-Skripte messen.
- lighthouserc.js liegt nicht am erwarteten Pfad. Findet treosh/lighthouse-ci-action die Datei unter dem angegebenen configPath nicht, fällt der Lauf auf die eingebauten Voreinstellungen zurück, ohne dass der Workflow das laut sichtbar meldet. Fix: den Pfad in configPath exakt gegen den tatsächlichen Speicherort der Datei im Repository prüfen.
- Der temporäre öffentliche Speicher wird als dauerhaftes Archiv missverstanden. Ein Team verlässt sich auf einen alten Berichtslink aus einem geschlossenen Pull Request und findet ihn nach einer Woche nicht mehr, weil temporary-public-storage Berichte automatisch löscht. Fix: für einen langfristigen Verlauf einen eigenen LHCI-Server mit serverBaseUrl betreiben.
- Alle Websites eines Portfolios teilen sich dieselben harten Schwellenwerte. Eine bildlastige Magazinseite und eine schlanke Landingpage haben strukturell unterschiedliche Ladezeiten, wodurch eine einzige gemeinsame Grenze entweder die Landingpage zu milde oder die Magazinseite dauerhaft zu streng prüft. Fix: pro Website oder Seitentyp eine eigene lighthouserc.js mit angepassten assertions pflegen.
Häufig gestellte Fragen
Was ist der Unterschied zwischen Lighthouse und Lighthouse CI?
Lighthouse ist Googles quelloffenes Prüfmodul, das eine einzelne Webseite in einer simulierten Umgebung analysiert und dieselben Kennzahlen liefert wie Chrome DevTools und PageSpeed Insights. Lighthouse CI, verpackt im npm-Paket @lhci/cli und im GitHub-Repository GoogleChrome/lighthouse-ci gepflegt, ist ein eigenständiges Werkzeug, das dieses Prüfmodul automatisiert in einer Build-Pipeline aufruft, die Ergebnisse mehrerer Durchläufe zusammenfasst und gegen festgelegte Schwellenwerte prüft. Ohne Lighthouse CI bleibt Lighthouse ein manuelles Werkzeug für den Einzelaufruf im Browser oder auf der Kommandozeile.
Welche Schwellenwerte gelten aktuell als gute Core Web Vitals?
Als gute Core-Web-Vitals-Werte gelten aktuell ein Largest Contentful Paint von 2,5 Sekunden oder darunter, eine Interaction to Next Paint von 200 Millisekunden oder darunter und ein Cumulative Layout Shift von 0,1 oder darunter, jeweils gemessen am 75. Perzentil der echten Seitenaufrufe auf Mobilgeräten und Desktop-Rechnern. Interaction to Next Paint hat seit dem 12. März 2024 die vorherige Kennzahl First Input Delay als dritte Core-Web-Vital-Metrik abgelöst. Eine Seite, die einen der drei Werte reißt, gilt für den betroffenen Anteil der Aufrufe als nicht bestehend, selbst wenn die anderen beiden Werte gut ausfallen.
Kann Lighthouse CI die Interaction to Next Paint direkt in der Build-Pipeline messen?
Lighthouse CI kann die Interaction to Next Paint nicht direkt in der Build-Pipeline messen, weil dieser Wert echte Nutzerinteraktionen voraussetzt, die in einem automatisierten Testlauf ohne Publikum gar nicht stattfinden. Stattdessen misst Lighthouse in der Build-Pipeline die Total Blocking Time, einen Laborwert, der laut Googles eigener Dokumentation stark mit einer schlechten Interaction to Next Paint korreliert, ohne ihr Ersatz zu sein. Die tatsächliche Interaction to Next Paint liefert erst echter Nutzerverkehr, etwa über den Bericht Core Web Vitals in der Google Search Console oder über eigenes Real User Monitoring.
Warum liefert Lighthouse CI bei zwei aufeinanderfolgenden Durchläufen unterschiedliche Werte?
Lighthouse CI liefert bei zwei aufeinanderfolgenden Durchläufen unterschiedliche Werte, weil Lighthouse selbst laut eigener Dokumentation von Netzwerkschwankungen, wechselnder Serverantwortzeit und der Auslastung des Testrechners beeinflusst wird, selbst wenn sich am Code nichts geändert hat. Ein einzelner Durchlauf kann dadurch um mehrere Punkte nach oben oder unten abweichen. Die Option numberOfRuns in der Konfigurationsdatei lässt Lighthouse CI stattdessen mehrere Durchläufe hintereinander ausführen und den Median als Referenzwert verwenden, was die Schwankung nach Angaben von Google deutlich verringert.