Performance-Regressionstests in der CI-Pipeline
60fps
ms
Performance · CI/CD · Lighthouse CI · Bundle Size
Performance-Regressionstests in der CI-Pipeline
Bundle-Size-Diffs und Lighthouse-Vergleiche als Pre-Merge-Gate

Performance-Regressionen entstehen selten durch eine einzelne dramatische Änderung, sondern durch viele kleine Verschlechterungen, die einzeln unter dem Radar bleiben. Eine CI-Pipeline, die Bundle-Größe und Lighthouse-Metriken bei jedem Pull Request automatisch gegen den Basis-Branch vergleicht, macht diese schleichende Verschlechterung sichtbar, bevor sie den Hauptzweig und damit die Produktion erreicht.

16 Min. Lesezeit Bundle-Size-Diff · Lighthouse CI · Statistische Signifikanz GitHub Actions · GitLab CI · Magento 2 · Hyvä Theme

1. Pre-Merge-Gate vs. Post-Merge-Monitoring

Ein Pre-Merge-Gate prüft Performance-Metriken, bevor Code in den Hauptzweig gelangt, und blockiert oder markiert den Pull Request bei einer Regression. Post-Merge-Monitoring über Real User Monitoring oder synthetische Checks auf Produktion erkennt Regressionen erst, nachdem sie bereits live sind. Beide Ansätze schließen sich nicht aus, sie lösen unterschiedliche Probleme: Post-Merge-Monitoring deckt Effekte auf, die nur unter echter Last, echten Netzwerken und echten Geräten sichtbar werden. Ein Pre-Merge-Gate verhindert, dass offensichtliche Regressionen überhaupt erst dorthin gelangen.

Der wirtschaftliche Unterschied liegt in den Korrekturkosten. Eine Regression, die im Pull Request auffällt, kostet den Autor wenige Minuten Nacharbeit, während derselbe Fehler in Produktion oft erst nach Tagen über sinkende Conversion-Zahlen oder eine CrUX-Verschlechterung auffällt und dann durch mehrere Commits, einen Revert oder ein Hotfix behoben werden muss. Für Magento- und Hyvä-Shops mit häufigen Deployments ist ein Pre-Merge-Gate deshalb keine Ergänzung, sondern die erste Verteidigungslinie, während Post-Merge-Monitoring die Kontrolle über die tatsächliche Nutzererfahrung behält.

2. Aufbau einer Regressionstest-Pipeline

Eine funktionierende Regressionstest-Pipeline braucht drei Bausteine: einen reproduzierbaren Build für den Pull-Request-Branch, eine Baseline-Messung für den Basis-Branch (meist main) und einen Vergleichsschritt, der beide Messungen gegenüberstellt. Die Baseline wird idealerweise nicht bei jedem PR neu gemessen, sondern nach jedem Merge in main einmal erzeugt und als Artefakt oder in einem kleinen Datenspeicher abgelegt. Das spart CI-Zeit und stellt sicher, dass alle Pull Requests gegen denselben, stabilen Referenzwert verglichen werden statt gegen einen erneut gemessenen, potenziell verrauschten Wert.

Der Vergleichsschritt selbst sollte als eigenständiger Job laufen, der Build und Baseline als Eingabe nimmt und einen strukturierten Diff als Ausgabe erzeugt, zum Beispiel im JSON-Format. Diese Trennung erlaubt es, denselben Vergleichslogik-Code sowohl für Bundle-Size- als auch für Lighthouse-Diffs wiederzuverwenden und ihn unabhängig vom eigentlichen Build-Prozess zu testen. Wichtig ist außerdem, dass die Pipeline denselben Build-Prozess für PR-Branch und Baseline verwendet, denn unterschiedliche Node- oder PHP-Versionen, unterschiedliche NODE_ENV-Werte oder abweichende Tailwind-Konfigurationen verfälschen den Vergleich unabhängig von echten Code-Änderungen.

3. Bundle-Size-Tracking pro Pull Request

Bundle-Size-Tracking misst die Größe der ausgelieferten JavaScript- und CSS-Dateien nach dem Build und vergleicht sie gegen denselben Build auf dem Basis-Branch. Entscheidend ist, nicht die unkomprimierte Rohgröße zu vergleichen, sondern die Größe nach Gzip oder Brotli, weil das der tatsächlich über das Netzwerk übertragenen Datenmenge entspricht. Für Hyvä-Themes bedeutet das konkret: web/tailwind/tailwind.css nach dem Purge-Schritt und die generierten Alpine.js-Bundles unter pub/static/frontend/ sind die relevanten Artefakte, nicht der unminifizierte Quellcode.

Ein einfaches, robustes Bash-Pattern checkt beide Branches nacheinander aus, baut sie identisch und summiert die Dateigrößen pro Kategorie. Der Diff wird als Prozentsatz relativ zur Basisgröße berechnet, nicht als absolute Byte-Differenz, weil ein Delta von 5 KB bei einem 20-KB-Bundle etwas völlig anderes bedeutet als bei einem 500-KB-Bundle. Ein Schwellenwert von beispielsweise 5 % Wachstum pro Kategorie lässt normale Entwicklung zu, verhindert aber, dass sich unbemerkte Aufblähung über viele kleine Pull Requests hinweg ansammelt.


#!/usr/bin/env bash
# bundle-size-diff.sh - Compare gzip bundle size between two git refs
set -euo pipefail

BASE_REF="${1:-origin/main}"
HEAD_REF="${2:-HEAD}"
THRESHOLD_PERCENT=5
BUNDLE_GLOB="pub/static/frontend/**/*.{js,css}"

measure_bundle_size() {
  local ref="$1"
  local worktree
  worktree="$(mktemp -d)"
  git worktree add --detach "$worktree" "$ref" >/dev/null
  ( cd "$worktree" && npm ci --silent && npm run build --silent )

  # Sum gzip-compressed size of all matching assets in bytes
  find "$worktree/pub/static/frontend" -type f \( -name "*.js" -o -name "*.css" \) \
    -exec gzip -c {} \; | wc -c

  git worktree remove --force "$worktree"
}

base_size="$(measure_bundle_size "$BASE_REF")"
head_size="$(measure_bundle_size "$HEAD_REF")"
delta=$(( head_size - base_size ))
percent=$(awk -v b="$base_size" -v d="$delta" 'BEGIN { printf "%.2f", (d / b) * 100 }')

echo "Base: ${base_size} bytes | Head: ${head_size} bytes | Delta: ${delta} bytes (${percent}%)"

if awk -v p="$percent" -v t="$THRESHOLD_PERCENT" 'BEGIN { exit !(p > t) }'; then
  echo "[FAIL] Bundle grew by ${percent}%, exceeds threshold of ${THRESHOLD_PERCENT}%"
  exit 1
fi
echo "[OK] Bundle size within threshold"

4. Diffs automatisch im Pull Request kommentieren

Ein Zahlenwert im CI-Log wird von den wenigsten Entwicklern aktiv gesucht. Deutlich wirksamer ist ein automatischer PR-Kommentar, der Bundle-Size- und Lighthouse-Diff direkt sichtbar macht, dort wo der Code-Review ohnehin stattfindet. Die gängige Technik dafür ist ein Sticky Comment: Statt bei jedem Pipeline-Lauf einen neuen Kommentar zu erzeugen, sucht der Bot nach einem vorhandenen Kommentar mit einem eindeutigen Marker (zum Beispiel einem versteckten HTML-Kommentar <!-- perf-bot-marker -->) und aktualisiert diesen, statt den Thread mit wiederholten Kommentaren zuzumüllen.

Der Kommentar sollte nicht nur die Gesamtzahl zeigen, sondern pro Datei oder Chunk aufschlüsseln, wo die Größenänderung herkommt, inklusive eines Links zum vollständigen Lighthouse-Report als Artefakt. Für Teams mit mehreren Storefronts oder Marken empfiehlt sich eine Tabelle pro Seite (Startseite, Kategorieseite, Produktseite), weil eine Regression oft nur eine einzelne Seitenvorlage betrifft und eine aggregierte Gesamtzahl das verschleiern würde. Ein status: failure auf dem entsprechenden GitHub-Check zusätzlich zum Kommentar macht das Ergebnis auch für Branch-Protection-Regeln verwertbar.


# .github/workflows/performance-regression.yml
name: Performance Regression Check
on:
  pull_request:
    branches: [main]

jobs:
  bundle-and-lighthouse-diff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

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

      # Restore cached base-branch build to avoid rebuilding main every run
      - name: Restore baseline artifact
        uses: actions/cache/restore@v4
        with:
          path: .baseline
          key: baseline-${{ github.event.pull_request.base.sha }}

      - name: Build PR branch
        run: npm ci && npm run build

      - name: Compare bundle size
        id: bundle
        run: bash ./ci/bundle-size-diff.sh origin/${{ github.base_ref }} HEAD >> "$GITHUB_OUTPUT"

      - name: Run Lighthouse CI on both branches
        run: npx @lhci/cli autorun --config=./lighthouserc.json

      - name: Post or update sticky PR comment
        uses: marocchino/sticky-pull-request-comment@v2
        with:
          header: perf-bot-marker
          message: |
            ## Performance Regression Report
            ${{ steps.bundle.outputs.summary }}

5. Lighthouse-Score-Diffing zwischen Branches

Lighthouse-Score-Diffing geht einen Schritt über reines Bundle-Tracking hinaus, weil eine kleinere JavaScript-Datei nicht automatisch eine schnellere Seite bedeutet. Die Pipeline baut beide Branches, deployed sie auf identisch konfigurierte, temporäre Umgebungen (zum Beispiel über Docker-Container mit demselben Seed-Datensatz) und führt Lighthouse CI gegen dieselben URLs auf beiden Umgebungen aus. Verglichen werden nicht nur der Performance-Score, sondern die Einzelmetriken LCP, TBT (Total Blocking Time als Labor-Näherung für INP) und CLS, weil eine Verschlechterung oft nur eine einzelne Metrik betrifft, während der aggregierte Score sie durch Verbesserungen in anderen Metriken verdeckt.

Entscheidend für belastbare Ergebnisse ist eine identische Testumgebung für beide Läufe: gleiche CPU-Drosselung, gleiche Netzwerk-Simulation, gleiche Anzahl an Wiederholungen. Lighthouse CI unterstützt das über numberOfRuns in der Konfiguration, wodurch mehrere Läufe pro URL erfolgen und der Median statt eines Einzelwerts verwendet wird. Für Magento-Shops mit Produktseiten, die je nach Kategorie unterschiedlich viele Bilder und Varianten laden, sollten mehrere repräsentative Seitentypen getestet werden, nicht nur die Startseite, da diese oft die schnellste und am wenigsten aussagekräftige Seite im gesamten Shop ist.


{
  "ci": {
    "collect": {
      "url": [
        "http://localhost:3000/",
        "http://localhost:3000/catalog/damen-jacken.html",
        "http://localhost:3000/catalog/product/view/id/1284"
      ],
      "numberOfRuns": 5,
      "settings": {
        "throttlingMethod": "simulate",
        "throttling": {
          "cpuSlowdownMultiplier": 4,
          "rttMs": 150,
          "throughputKbps": 1600
        }
      }
    },
    "assert": {
      "assertions": {
        "categories:performance": ["error", { "minScore": 0.85 }],
        "largest-contentful-paint": ["error", { "maxNumericValue": 2500 }],
        "total-blocking-time": ["error", { "maxNumericValue": 300 }],
        "cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }]
      }
    },
    "upload": {
      "target": "temporary-public-storage"
    }
  }
}

6. Statistisch signifikante Änderungen automatisch erkennen

Ein einfacher Zahlenvergleich zwischen zwei Lighthouse-Läufen führt zu unbrauchbaren Ergebnissen, weil jeder einzelne Lauf bereits ohne Code-Änderung um mehrere hundert Millisekunden schwankt. Die Lösung ist, nicht einen einzelnen Wert, sondern eine Verteilung aus mehreren Läufen pro Branch zu vergleichen und erst dann eine Regression zu melden, wenn der Unterschied zwischen den Medianen eine definierte Toleranzschwelle überschreitet, üblicherweise kombiniert aus einem relativen Prozentsatz (zum Beispiel 10 % LCP-Verschlechterung) und einem absoluten Mindestwert (zum Beispiel mindestens 150 Millisekunden), damit winzige Prozentsprünge bei bereits sehr schnellen Metriken nicht fälschlich als Regression zählen.

Ein Node-Skript, das zwei Lighthouse-JSON-Reports einliest, eignet sich gut, um diese Logik zentral zu implementieren und für alle Metriken konsistent anzuwenden, statt sie in jedem Workflow neu zu duplizieren. Wichtig ist, dass das Skript pro Metrik unterschiedliche Schwellenwerte erlaubt, weil CLS naturgemäß in einem viel kleineren Wertebereich schwankt als LCP und deshalb einen anderen relativen Schwellenwert braucht. Das Ergebnis sollte als strukturiertes JSON zurückgegeben werden, damit es sowohl für den PR-Kommentar als auch für den Exit-Code der Pipeline weiterverwendet werden kann.


// compare-lighthouse-reports.js - Flag statistically significant regressions
const fs = require('node:fs');

const METRIC_THRESHOLDS = {
  'largest-contentful-paint': { relativePercent: 10, absoluteMinMs: 150 },
  'total-blocking-time': { relativePercent: 15, absoluteMinMs: 50 },
  'cumulative-layout-shift': { relativePercent: 15, absoluteMinMs: 0.01 },
};

function median(values) {
  const sorted = [...values].sort((a, b) => a - b);
  const mid = Math.floor(sorted.length / 2);
  return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
}

function loadMedianMetrics(reportPaths) {
  const runs = reportPaths.map((p) => JSON.parse(fs.readFileSync(p, 'utf8')));
  const result = {};
  for (const metric of Object.keys(METRIC_THRESHOLDS)) {
    result[metric] = median(runs.map((r) => r.audits[metric].numericValue));
  }
  return result;
}

function diffMetrics(baseReports, headReports) {
  const base = loadMedianMetrics(baseReports);
  const head = loadMedianMetrics(headReports);
  const regressions = [];

  for (const [metric, { relativePercent, absoluteMinMs }] of Object.entries(METRIC_THRESHOLDS)) {
    const delta = head[metric] - base[metric];
    const percent = (delta / base[metric]) * 100;

    // Flag only if BOTH the relative and absolute thresholds are exceeded
    if (percent > relativePercent && delta > absoluteMinMs) {
      regressions.push({ metric, base: base[metric], head: head[metric], percent: percent.toFixed(1) });
    }
  }
  return regressions;
}

const regressions = diffMetrics(process.argv.slice(2, 6), process.argv.slice(6, 10));
console.log(JSON.stringify({ regressions, hasRegression: regressions.length > 0 }, null, 2));
process.exit(regressions.length > 0 ? 1 : 0);

7. Rauschen in CI-Runnern beherrschen

CI-Runner auf geteilten Cloud-Infrastrukturen liefern keine konstante Rechenleistung: Nachbar-Container auf demselben Host, wechselnde CPU-Generationen und variable Netzwerklatenz erzeugen eine Streuung, die bei einer Einzelmessung leicht mit einer echten Regression verwechselt wird. Wer diese Varianz ignoriert, bekommt entweder ständig False Positives, die das Team dazu bringen, Warnungen zu ignorieren, oder senkt die Schwellenwerte so weit, dass echte Regressionen ebenfalls durchrutschen. Beides untergräbt das Vertrauen in die gesamte Pipeline.

Die wirksamste Gegenmaßnahme ist die Kombination aus mehreren Wiederholungen pro Messung (fünf Lighthouse-Läufe statt einem), der Verwendung des Medians statt des Mittelwerts, weil der Median robuster gegen einzelne Ausreißer ist, und dedizierten, gleich dimensionierten Runnern für performance-kritische Jobs statt der günstigsten verfügbaren Instanz. Zusätzlich hilft ein Warm-up-Lauf vor der eigentlichen Messung, der nicht gewertet wird, aber Caching-Effekte auf Betriebssystem- und Docker-Ebene ausgleicht, sodass der erste gemessene Lauf nicht systematisch langsamer ist als die folgenden.

8. CI-Laufzeitkosten gegen Gründlichkeit abwägen

Ein vollständiger Lighthouse-Audit mit fünf Wiederholungen über mehrere Seitentypen und beide Branches kostet schnell mehrere Minuten CI-Zeit pro Pull Request, was sich bei einem aktiven Team mit zwanzig PRs am Tag zu erheblichen Kosten und langen Wartezeiten summiert. Nicht jeder Pull Request braucht denselben Prüfumfang: Eine reine Textänderung im CMS-Content oder eine Übersetzungsdatei hat keinen Einfluss auf Bundle-Größe oder Rendering-Performance und muss den vollen Audit nicht durchlaufen.

Ein praktikabler Ansatz ist Path-basiertes Filtering: Der volle Regressionstest läuft nur, wenn sich Dateien in web/`, `Magento_Theme/templates oder JavaScript-/CSS-Quellverzeichnissen geändert haben. Für alle anderen PRs reicht ein schneller, günstiger Bundle-Size-Check ohne vollen Lighthouse-Lauf. Ergänzend eignet sich ein Label-gesteuerter Full-Audit, den Reviewer manuell mit einem perf-audit-Label auslösen, sowie ein nächtlicher, vollständiger Lauf gegen main, der Drift über Zeit erkennt, die einzelne PR-Diffs wegen kumulativ kleiner Änderungen unter dem Schwellenwert übersehen.

9. Build-Artefakte cachen und Strategien im Vergleich

Caching von Build-Artefakten ist der zweite große Hebel neben Sampling, um die Pipeline schnell zu halten. Der Node-Modules-Cache, der Tailwind-JIT-Cache und vor allem der bereits gebaute Baseline-Branch sollten zwischen Pipeline-Läufen wiederverwendet werden, statt bei jedem PR neu erzeugt zu werden. Ein Cache-Key, der den Lockfile-Hash und den Basis-Branch-Commit-SHA kombiniert, stellt sicher, dass der Cache exakt dann invalidiert wird, wenn sich Abhängigkeiten oder die Baseline tatsächlich geändert haben, und nicht öfter.

Die folgende Übersicht vergleicht gängige Ansätze zur Regressionserkennung in der CI-Pipeline nach Erkennungszeitpunkt und typischer Schwachstelle.

Strategie Erkennungszeitpunkt Typische Schwachstelle Empfehlung
Kein automatisierter Check Erst nach dem Deploy Regression erreicht Produktion unbemerkt Automatisiertes Pre-Merge-Gate einführen
Manueller PR-Review Vor dem Merge, aber unzuverlässig Reviewer übersieht Bundle-Wachstum von wenigen KB Automatischer Bot-Kommentar mit Diff
Nur Post-Merge-RUM Tage bis Wochen nach dem Merge Nutzer bereits betroffen, Ursache schwer rückverfolgbar Pre-Merge-Gate als Ergänzung, nicht Ersatz
Rohvergleich einzelner Lighthouse-Läufe Vor dem Merge, aber verrauscht Flaky Fails durch CI-Runner-Varianz Median aus mehreren Läufen plus Toleranzband
Kombiniertes Bundle- und Lighthouse-Gate mit Sampling Vor dem Merge, gezielt gewichtet Erfordert initialen Konfigurationsaufwand Path-Filter plus nächtlicher Full-Audit gegen main

Für GitLab CI sieht die Cache-Konfiguration technisch anders aus als bei GitHub Actions, folgt aber demselben Prinzip: Abhängigkeiten und Build-Ausgaben über einen stabilen Key zwischenspeichern, damit wiederholte Pipeline-Läufe nicht bei null anfangen.


# .gitlab-ci.yml - Cache dependencies and build output to keep the pipeline fast
performance-regression:
  stage: test
  image: node:20-alpine
  rules:
    - changes:
        - "src/app/design/frontend/**/web/**/*"
        - "src/app/design/frontend/**/*.phtml"
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - node_modules/
      - .npm/
    policy: pull-push
  variables:
    NPM_CONFIG_CACHE: "$CI_PROJECT_DIR/.npm"
  before_script:
    - npm ci --prefer-offline --cache .npm
  script:
    - npm run build
    - bash ./ci/bundle-size-diff.sh origin/main HEAD
    - npx @lhci/cli autorun --config=./lighthouserc.json
  artifacts:
    when: always
    paths:
      - .lighthouseci/
    expire_in: 14 days

Mironsoft

Performance-Engineering, CI/CD-Pipelines und Monitoring für Magento-Shops

Performance-Regressionen automatisch abfangen?

Wir richten Bundle-Size-Tracking und Lighthouse-Diffing als Pre-Merge-Gate in eurer CI-Pipeline ein, inklusive robuster Schwellenwerte gegen CI-Rauschen und einer Sampling-Strategie, die eure Pipeline schnell hält.

CI-Pipeline-Audit

Bestehende Pipeline analysieren und Regressionslücken identifizieren

Gate-Implementierung

Bundle-Diff, Lighthouse CI und PR-Kommentare produktiv einrichten

Kosten-Optimierung

Caching und Sampling, damit die Pipeline schnell und günstig bleibt

10. Zusammenfassung

Performance-Regressionstests in der CI-Pipeline lösen ein Problem, das rein manuelle Code-Reviews strukturell nicht lösen können: die Summe vieler kleiner, für sich genommen unauffälliger Verschlechterungen. Ein Pre-Merge-Gate, das Bundle-Größe nach Gzip und Lighthouse-Kernmetriken automatisch gegen den Basis-Branch vergleicht, macht diese Verschlechterung sichtbar, bevor sie in Produktion gelangt. Entscheidend für die Akzeptanz im Team ist, dass die Pipeline nicht durch CI-Rauschen ständig falschen Alarm schlägt: Median aus mehreren Läufen, kombinierte relative und absolute Schwellenwerte sowie ein Sticky-PR-Kommentar statt eines vergrabenen Log-Eintrags sorgen dafür, dass Entwickler den Warnungen tatsächlich vertrauen und darauf reagieren.

Gründlichkeit und CI-Laufzeit stehen dabei in einem direkten Zielkonflikt, der sich nicht durch mehr Rechenleistung allein lösen lässt. Path-basiertes Filtering, damit reine Content-Änderungen keinen vollen Audit auslösen, gecachte Baseline-Builds statt wiederholter Neuberechnung und ein nächtlicher Full-Audit als Sicherheitsnetz gegen kumulative Drift halten die Pipeline für die meisten Pull Requests unter einer Minute, ohne bei tatsächlich relevanten Änderungen an Aussagekraft zu verlieren.

Performance-Regressionstests in der CI-Pipeline - Das Wichtigste auf einen Blick

Pre-Merge-Gate

Bundle-Size- und Lighthouse-Vergleich vor dem Merge fängt Regressionen ab, bevor sie Produktion erreichen. Ergänzt, ersetzt nicht Post-Merge-Monitoring.

Bundle-Size-Diff

Gzip-Größe pro Kategorie gegen Basis-Branch vergleichen, Ergebnis als prozentualer Schwellenwert, nicht als absolute Byte-Differenz.

Statistische Signifikanz

Median aus mehreren numberOfRuns, kombinierte relative und absolute Schwellenwerte gegen CI-Rauschen und False Positives.

Kosten & Caching

Path-basiertes Filtering, gecachte Baseline-Builds und nächtlicher Full-Audit halten die Pipeline schnell und günstig.

11. FAQ: Performance-Regressionstests in der CI-Pipeline

1Was ist der Unterschied zwischen Pre-Merge- und Post-Merge-Performance-Monitoring?
Ein Pre-Merge-Gate prüft im Pull Request und blockiert vor dem Merge. Post-Merge-Monitoring erkennt Regressionen erst, nachdem sie live sind. Beide ergänzen sich, das Gate verhindert die teureren Nacharbeiten in Produktion.
2Wie berechnet man den Bundle-Size-Diff zwischen zwei Branches?
Beide Branches identisch bauen, gzip-Größe der Assets summieren und als Prozentsatz relativ zur Basisgröße vergleichen, nicht als absolute Byte-Differenz.
3Wie kommentiert man den Diff automatisch im Pull Request?
Über einen Sticky Comment mit eindeutigem Marker, der bei jedem Lauf aktualisiert statt neu erzeugt wird. Tools wie sticky-pull-request-comment übernehmen das für GitHub Actions.
4Wie funktioniert Lighthouse-Score-Diffing zwischen zwei Branches?
Beide Branches auf identischen temporären Umgebungen deployen, mit Lighthouse CI testen und Einzelmetriken wie LCP, TBT und CLS als Median mehrerer Läufe vergleichen.
5Warum sind rohe Lighthouse-Vergleiche anfällig für False Positives?
Ein einzelner Lauf schwankt allein durch CI-Runner-Varianz um mehrere hundert Millisekunden. Ein Rohvergleich zweier Einzelläufe verwechselt diese Streuung leicht mit einer echten Regression.
6Wie vermeidet man Flaky Fails durch verrauschte CI-Runner?
Mehrere Wiederholungen und Median statt Einzelwert, dedizierte statt günstigste Runner, plus ungewerteter Warm-up-Lauf vor der eigentlichen Messung.
7Welche Schwellenwerte sind sinnvoll für Bundle-Size- und Lighthouse-Regressionen?
Kombination aus relativem Prozentsatz und absolutem Mindestwert, zum Beispiel 10 % UND mindestens 150 ms Delta, damit winzige Prozentsprünge bei schnellen Metriken nicht fälschlich zählen.
8Wann lohnt sich ein vollständiger Lighthouse-Audit nicht bei jedem PR?
Bei reinen Content- oder Übersetzungsänderungen ohne Einfluss auf Bundle oder Rendering. Path-basiertes Filtering löst den vollen Audit nur bei relevanten Verzeichnisänderungen aus.
9Wie hält man Build-Artefakte-Caching in der CI-Pipeline schnell?
Node-Modules-, Tailwind-JIT- und Baseline-Build-Caches über einen Key aus Lockfile-Hash und Basis-Branch-SHA zwischenspeichern, damit unnötige Invalidierung vermieden wird.
10Sollte ein Performance-Regressionstest den Merge blockieren oder nur warnen?
Bei klaren Überschreitungen der kombinierten Schwellenwerte blockieren, da False Positives bereits ausgefiltert sind. Bei Grenzfällen nahe der Schwelle zunächst warnen mit manueller Freigabe.