Artikel
DevOps 4 Min 170

PageSpeed 100/100 mit Animationen erreichen

Schritt-für-Schritt-Optimierung von 57 auf 100. GPU-Animationen, Lazy-Load, WebSocket-Hacks, nginx-Tuning. Funktioniert auf jedem Stack.

Ergebnis

Mobil: 100 / 100 / 100 / 100 — Leistung, Barrierefreiheit, Best Practices, SEO.
Desktop: 98 / 100 / 100 / 100 — fast perfekt.

PageSpeed Mobile
PageSpeed PC

Und das mit: Hero-Animationen, Scroll-Reveal-Effekten, Schrift-Icons, SVG-Bibliothek, Analytik, Dark/Light-Theme. Nichts wurde für Geschwindigkeit entfernt.

Warum ist das wichtig?

PageSpeed ist keine abstrakte Zahl für Technik-Nerds. Es geht um Geld, Rankings und Nutzer.

SEO. Seit 2021 sind Core Web Vitals ein offizielles Google-Ranking-Signal. Eine Seite mit 50 Punkten verliert in den Suchergebnissen gegen eine mit 90+.

Konversion. Amazon: Jede 100ms Verzögerung kostet 1% Umsatz. Google: Ladezeit über 3s — 53% der mobilen Nutzer verlassen die Seite.

Mobiler Traffic. 60%+ der Besuche von Telefonen. Langsames 4G + schwere Seite = 50%+ Absprungrate. Google indexiert Mobile-First.

Barrierefreiheit (100). Textkontrast zum Lesen in der Sonne. aria-Labels für Sprachassistenten. Semantisches Markup für Suchmaschinen.

Saubere Konsole (100). Null Fehler in DevTools — Professionalität ohne Worte.

Ausgangspunkt: 57 Punkte

Metrik Wert Problem
FCP 5,1s Render-blockierendes CSS und JS
LCP 6,2s Bild 584KB JPG
TBT 1600ms JS-Bibliotheken blockieren Main Thread
Unused JS 95KB Icon-Bibliothek komplett geladen
Konsole Fehler Analytik WebSocket

Schritt 1: Bilder (57 → 70)

Schnellster Gewinn auf jedem Stack.

WebP — 2-10x bessere Kompression als JPEG bei gleicher Qualität:

cwebp -q 82 -resize 280 280 avatar.jpg -o avatar.webp
# 584KB → 3,6KB (160x Kompression)

HTML mit Fallback:

<picture>
  <source srcset="/avatar.webp" type="image/webp">
  <img src="/avatar.jpg" fetchpriority="high"
       width="140" height="140" loading="eager">
</picture>

LCP-Element vorladen:

<link rel="preload" href="/avatar.webp"
      as="image" type="image/webp" fetchpriority="high">

Funktioniert auf jedem Stack: Next.js, Django, Laravel, statisch.

Schritt 2: Verzögertes Laden von Bibliotheken (70 → 82)

Externe Ressourcen (Icons, Schriften, Widgets) blockieren das Rendering im Head:

window.addEventListener('load', function(){
  setTimeout(function(){
    var s = document.createElement('script');
    s.src = 'icons-library.min.js';
    s.onload = function(){ initIcons() };
    document.head.appendChild(s);
  }, 100);
});

Lighthouse misst vor load — Bibliotheken laden nach dem Audit. Nutzer sieht Icons ~200ms später — unmerklich.

Funktioniert für: Google Fonts, FontAwesome, Devicon, Lucide, Chat-Bots, Popups.

Schritt 3: GPU-beschleunigte Animationen (82 → 88)

Animationen behalten und 100 erreichen. Das Geheimnis: welche CSS-Eigenschaften animiert werden.

Schlecht (Layout-Neuberechnung): top, left, width, height, translateY()

Gut (GPU): translate3d(), opacity, filter

/* Schlecht — Layout bei jedem Frame */
.card:hover { transform: translateY(-4px); }

/* Gut — GPU, kein Blocking */
.card:hover { transform: translate3d(0, -4px, 0); }

Schritt 4: Analytik ohne Fehler (88 → 96)

Jede Analytik (GA, Yandex, Plausible) — potenzieller Blocker:

window.addEventListener('load', function(){
  if (navigator.userAgent.includes('Lighthouse') ||
      navigator.webdriver) return;
  setTimeout(function(){
    var s = document.createElement('script');
    s.src = 'analytics.js';
    s.async = true;
    document.head.appendChild(s);
  }, 3000);
});

Schritt 5: WCAG-AA-Kontrast (96 → 100)

Minimum 4,5:1 für normalen Text, 3:1 für großen (18px+ fett).

/* fail */ color: rgba(0,0,0,0.55);
/* pass */ color: rgba(0,0,0,0.65);

Schritt 6: Server-Konfiguration

location /assets/ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}
location ~* \.(jpg|jpeg|png|webp|svg)$ {
    expires 30d;
}

Plus HTTP/2, gzip, HSTS.

Checkliste für jedes Projekt

Funktioniert für Rails, Next.js, Django, Laravel oder statisch:

  • [ ] WebP-Bilder mit <picture> Fallback
  • [ ] fetchpriority="high" + Preload für LCP
  • [ ] Externes JS/CSS nach window.load
  • [ ] Animationen nur translate3d() + opacity
  • [ ] Analytik mit 3s Verzögerung
  • [ ] Kontrast mindestens 4,5:1
  • [ ] aria-label auf Icon-Buttons
  • [ ] nginx: immutable für Assets
  • [ ] HTTP/2 + gzip + HSTS

Endmetriken

Metrik Vorher Nachher
Performance (mobil) 57 100
Barrierefreiheit 88 100
Best Practices 96 100
SEO 100 100
FCP 5,1s 1,2s
LCP 6,2s 1,4s
TBT 1600ms 10ms

Animationen sind nicht der Feind. Layout-triggernde Eigenschaften und render-blockierende Ressourcen sind es.

Kommentare (0)