$30 off During Our Annual Pro Sale. View Details »

Ladezeitenoptimierung für SEOs: PageSpeed Extrem mit Kai Spriestersbach

Ladezeitenoptimierung für SEOs: PageSpeed Extrem mit Kai Spriestersbach

In diesem Online-Vortrag erkläre ich kurz die wichtigsten Basics in Sachen Ladezeitenoptimierung und gehe dann auf ein paar sehr effektive Tricks ein, die massiv bei der Verbesserung der PageSpeed-Werte helfen. Insbesondere die TTFB, sowie das Rendering werden durch die gezeigten Techniken drastisch verbessert.

Hier geht es zu meinem vollständigen Online-Seminar:
https://www.search-one.de/online-seminar-pagespeed/

Kai Spriestersbach

December 09, 2020
Tweet

More Decks by Kai Spriestersbach

Other Decks in Programming

Transcript

  1. Pagespeed Extreme
    Kai Spriestersbach

    View Slide

  2. Research & Development bei der eology GmbH
    • B.Sc. E-Commerce

    • Mediengestalter IHK

    • Lehrbeauftragter an der FHWS

    • Inhaber von SEARCH ONE

    • Aus- und Weiterbildung von Mitarbeitern

    • Speaker auf SMX, SEOkomm, SEO-Day,
    OMK, OMKB, etc.
    Kai Spriestersbach

    View Slide

  3. SEO aus Leidenschaft
    • Online seit 1996

    • Web-Design seit 2001

    • Web-Entwicklung 2004

    • SEO seit 2008

    • Selbstständig seit 2012
    Kai Spriestersbach
    Matt Cutts
    Head Of Web Spam, Google
    Sie könnten mich kennen von

    View Slide

  4. Neuer Rankingfaktor
    Page Experience

    View Slide

  5. https://webmasters.googleblog.com/2020/05/evaluating-page-experience.html

    View Slide

  6. https://webmasters.googleblog.com/2020/05/evaluating-page-experience.html

    View Slide

  7. https://webmasters.googleblog.com/2020/05/evaluating-page-experience.html

    View Slide

  8. https://webmasters.googleblog.com/2020/05/evaluating-page-experience.html

    View Slide

  9. https://webmasters.googleblog.com/2020/05/evaluating-page-experience.html

    View Slide

  10. https://webmasters.googleblog.com/2020/05/evaluating-page-experience.html

    View Slide

  11. Mehr unter: https://kai.im/pagespeed
    Mein Online-Seminar 

    Web Vitals & PageSpeed
    +

    View Slide

  12. PageSpeed Basics

    View Slide

  13. PageSpeed Basics
    Daran führt kein Weg vorbei
    • HTTP/2 (Test: https://http2.pro/)

    • Cache-Control & ETags

    • GZIP, besser noch brotli

    • Bilder

    • Responsive Images

    • Nur in dargestellter Größe einbetten

    • Lazy Load für Bilder & Videos

    • Kompression via JPG + PNG + WebP (+ Avif)

    View Slide

  14. TTFB Optimierung

    View Slide

  15. TTFB = Time To First Byte

    View Slide

  16. Deshalb ist die TTFB so wichtig!
    https://www.webpagetest.org/

    View Slide

  17. Deshalb ist die TTFB so wichtig!
    }
    GEFÜHLT
    PASSIERT
    NIX!
    https://www.webpagetest.org/

    View Slide

  18. Was passiert vor dem 1. Byte?
    • Domain wird via DNS aufgelöst

    • TCP-Verbindung wird aufgebaut

    SYN, SYN-ACK, ACK

    • TLS-Handshake für SSL-Verbindung

    • Request wird an den Server gesendet

    TTFB
    https://www.mozilla.org/de/firefox/browsers/compare/

    https://www.cloudflare.com/learning/dns/what-is-dns/

    https://www.cloudflare.com/de-de/learning/ssl/what-happens-in-a-tls-handshake/
    TCP
    ~50ms
    TLS
    ~110ms
    DNS
    ~50ms

    View Slide

  19. Puh… wir warten immer noch auf das erste Byte!
    • HTTP Request

    • CGI-Request

    • PHP-Script laden

    • PHP ausführen

    • Datenbank abfragen

    • HTML rendern

    • HTTP Response mit HTML senden
    TTFB
    GET / HTTP/1.1
    Host: www.example.com Request /
    index.php
    SELECT column1, colum
    FROM table_name;
    Built HTML
    HTTP/1.1 200 OK
    Date: Mon, 27 Jul 2020 12:28:53 GMT
    Server: NGINX
    Content-Length: 88
    Content-Type: text/html
    Connection: Closed


    Hello, World!


    View Slide

  20. Puh… wir warten immer noch auf das erste Byte!
    • HTTP Request

    • CGI-Request

    • PHP-Script laden

    • PHP ausführen

    • Datenbank abfragen

    • HTML rendern

    • HTTP Response mit HTML senden
    TTFB
    GET / HTTP/1.1
    Host: www.example.com Request /
    index.php
    SELECT column1, colum
    FROM table_name;
    Built HTML
    HTTP/1.1 200 OK
    Date: Mon, 27 Jul 2020 12:28:53 GMT
    Server: NGINX
    Content-Length: 88
    Content-Type: text/html
    Connection: Closed


    Hello, World!


    View Slide

  21. 1. Full Page Cache aktivieren
    • Fertig generiertes HTML wird im RAM vorgehalten

    • Alle unbekannten Nutzer erhalten statisches HTML

    • Cookie-/Pfadbasierte Ausnahmen

    • PHP, HDD & DB werden nicht benötigt!
    TTFB Optimierung
    Request /
    Cached HTML
    ..zZz
    RAM

    View Slide

  22. 2. Opcode, Object In-Memory Cache + NVMe nutzen
    • Schnellste SSDs (NVMe) statt drehender Platten

    • Bereits vorprozessierter PHP-Code wird gespeichert

    • Häufig benutze Objekte/Fragmente werden persistent gespeichert

    • Häufige Datenbankabfragen werden im RAM gehalten

    • Beschleunigt selbst dynamische Webseiten!
    TTFB Optimierung

    View Slide

  23. 3. CDN verwenden
    • Schnellster DNS + AnyCast IP

    • Hosting in weltweiten Datencentern = Nah am Kunden

    • Argo Routing = Schnellster Weg

    • Seiten liegen bereits fertig gerendert im CDN

    • On-The-Fly Content Optimierung möglich (Bilder, Kompression, etc.)
    TTFB Optimierung

    View Slide

  24. Rendering verbessern

    View Slide

  25. Rendering „sichtbar“ machen
    https://developers.google.com/web/fundamentals/performance/critical-rendering-path?hl=de
    Progressives
    Rendering
    Unoptimiertes
    Rendering

    View Slide

  26. Der kritische Rendering-Pfad
    https://bitsofco.de/understanding-the-critical-rendering-path/

    View Slide

  27. Performance in den Chrome Developer Tools

    View Slide

  28. View Slide

  29. Non-blocking CSS
    Inline CSS im
    Media-Attribut

    View Slide

  30. Critical CSS

    View Slide

  31. Critical CSS Tool
    https://criticalcss.com/

    View Slide

  32. Critical CSS Tool
    https://criticalcss.com/

    View Slide

  33. Third-Party Tags reduzieren
    https://www.webpagetest.org/video/view.php?id=190919_Di27491eeccb968f96eda867ddabf2ff3c8c24ed3d

    View Slide

  34. Third-Party Tags reduzieren
    https://www.webpagetest.org/video/view.php?id=190919_Di27491eeccb968f96eda867ddabf2ff3c8c24ed3d

    View Slide

  35. Async & Deferred JavaScript

    View Slide

  36. View Slide

  37. View Slide

  38. View Slide

  39. View Slide

  40. >80% des JS ist nicht aufschiebbar!
    https://w3techs.com/technologies/overview/javascript_library https://trends.builtwith.com/javascript

    View Slide

  41. Alles hört auf „DOM ready“

    View Slide

  42. View Slide

  43. Wahrgenommene Ladezeit

    View Slide

  44. Skeleton Screens
    https://css-tricks.com/building-skeleton-screens-css-custom-properties/

    View Slide

  45. Abstrakte Darstellung genügt!
    https://css-tricks.com/building-skeleton-screens-css-custom-properties/

    View Slide

  46. View Slide

  47. Web Fonts

    View Slide

  48. Font Rendering verbessern
    https://fonts.google.com/specimen/Roboto

    View Slide

  49. So bitte nicht!
    CSS-Datei herunterladen
    CSS prozessieren
    DNS Auflösung
    TCP-Verbindungsaufbau
    SSL-Handshake
    WebFont herunterladen
    WebFont rendern
    DNS Auflösung
    TCP-Verbindungsaufbau
    SSL-Handshake
    Text anzeigen
    HTML geladen

    View Slide

  50. Das können wir uns sparen
    CSS-Datei herunterladen
    CSS prozessieren
    DNS Auflösung
    TCP-Verbindungsaufbau
    SSL-Handshake
    WebFont herunterladen
    WebFont rendern
    DNS Auflösung
    TCP-Verbindungsaufbau
    SSL-Handshake
    Text anzeigen
    HTML geladen

    View Slide

  51. Also besser so…
    CSS-Datei herunterladen
    CSS prozessieren
    WebFont herunterladen
    WebFont rendern
    Text anzeigen
    HTML geladen

    View Slide

  52. Also besser so…
    CSS-Datei herunterladen
    CSS prozessieren
    WebFont herunterladen
    WebFont rendern
    Text anzeigen
    HTML geladen
    https://web.dev/font-display/

    View Slide

  53. Also besser so…
    CSS-Datei herunterladen
    CSS prozessieren
    WebFont herunterladen
    WebFont rendern
    Text anzeigen
    HTML geladen

    View Slide

  54. Also besser so…
    CSS-Datei herunterladen
    CSS prozessieren
    WebFont herunterladen
    WebFont rendern
    Text anzeigen
    HTML geladen

    View Slide

  55. Smart Font Reducing

    View Slide

  56. https://transfonter.org/ Danke an Daniel Abromeit @der_abro

    View Slide

  57. https://github.com/hakatashi/unicode-map

    View Slide

  58. View Slide

  59. View Slide

  60. Was bringt Smart Font Reducing?
    4 DNS Requests

    30 HTTP-Requests

    300 KB Daten
    via Google Fonts Selfhosted reduced Font
    0 DNS Requests

    1 HTTP-Requests

    20 KB Daten

    View Slide

  61. Smart Preloading

    View Slide

  62. View Slide

  63. View Slide

  64. View Slide

  65. View Slide

  66. HOME

    View Slide

  67. HOME

    View Slide

  68. View Slide

  69. Mouse Over,
    ARTICLE
    HOME

    View Slide

  70. Universal Hover-Preloader
    /**
    * Copyright (c) 2020 Google Inc
    *
    * Permission is hereby granted, free of charge, to any person obtaining a copy of
    * this software and associated documentation files (the "Software"), to deal in
    * the Software without restriction, including without limitation the rights to
    * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
    * the Software, and to permit persons to whom the Software is furnished to do so,
    * subject to the following conditions:
    *
    * The above copyright notice and this permission notice shall be included in all
    * copies or substantial portions of the Software.
    *
    * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
    * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
    * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    */
    const exposed = {};
    if (location.search) {
    var a = document.createElement("a");
    a.href = location.href;
    a.search = "";
    history.replaceState(null, null, a.href);
    }
    function tweet_(url) {
    open(
    "https://twitter.com/intent/tweet?url=" + encodeURIComponent(url),
    "_blank"
    );
    }
    function tweet(anchor) {
    tweet_(anchor.getAttribute("href"));
    }
    expose("tweet", tweet);
    function share(anchor) {
    var url = anchor.getAttribute("href");
    event.preventDefault();
    if (navigator.share) {
    navigator.share({
    url: url,
    });
    } else if (navigator.clipboard) {
    navigator.clipboard.writeText(url);
    message("Article URL copied to clipboard.");
    } else {
    tweet_(url);
    }
    }
    expose("share", share);
    function message(msg) {
    var dialog = document.getElementById("message");
    dialog.textContent = msg;
    dialog.setAttribute("open", "");
    setTimeout(function () {
    dialog.removeAttribute("open");
    }, 3000);
    }
    function prefetch(e) {
    if (e.target.tagName != "A") {
    return;
    }
    if (e.target.origin != location.origin) {
    return;
    }
    var l = document.createElement("link");
    l.rel = "prefetch";
    l.href = e.target.href;
    document.head.appendChild(l);
    }
    document.documentElement.addEventListener("mouseover", prefetch, {
    capture: true,
    passive: true,
    });
    document.documentElement.addEventListener("touchstart", prefetch, {
    capture: true,
    passive: true,
    });
    const GA_ID = document.documentElement.getAttribute("ga-id");
    window.ga =
    window.ga ||
    function () {
    if (!GA_ID) {
    return;
    }
    (ga.q = ga.q || []).push(arguments);
    };
    ga.l = +new Date();
    ga("create", GA_ID, "auto");
    ga("set", "transport", "beacon");
    var timeout = setTimeout(
    (onload = function () {
    clearTimeout(timeout);
    ga("send", "pageview");
    }),
    1000
    );
    var ref = +new Date();
    function ping(event) {
    var now = +new Date();
    if (now - ref < 1000) {
    return;
    }
    ga("send", {
    hitType: "event",
    eventCategory: "page",
    eventAction: event.type,
    eventLabel: Math.round((now - ref) / 1000),
    });
    ref = now;
    }
    addEventListener("pagehide", ping);
    addEventListener("visibilitychange", ping);
    addEventListener(
    "click",
    function (e) {
    var button = e.target.closest("button");
    if (!button) {
    return;
    }
    ga("send", {
    hitType: "event",
    eventCategory: "button",
    eventAction: button.getAttribute("aria-label") || button.textContent,
    });
    },
    true
    );
    var selectionTimeout;
    addEventListener(
    "selectionchange",
    function () {
    clearTimeout(selectionTimeout);
    var text = String(document.getSelection()).trim();
    if (text.split(/[\s\n\r]+/).length < 3) {
    return;
    }
    selectionTimeout = setTimeout(function () {
    ga("send", {
    hitType: "event",
    eventCategory: "selection",
    eventAction: text,
    });
    }, 2000);
    },
    true
    );
    if (window.ResizeObserver && document.querySelector("header nav #nav")) {
    var progress = document.getElementById("reading-progress");
    var timeOfLastScroll = 0;
    var requestedAniFrame = false;
    function scroll() {
    if (!requestedAniFrame) {
    requestAnimationFrame(updateProgress);
    requestedAniFrame = true;
    }
    timeOfLastScroll = Date.now();
    }
    addEventListener("scroll", scroll);
    var winHeight = 1000;
    var bottom = 10000;
    function updateProgress() {
    requestedAniFrame = false;
    var percent = Math.min(
    (document.scrollingElement.scrollTop / (bottom - winHeight)) * 100,
    100
    );
    progress.style.transform = `translate(-${100 - percent}vw, 0)`;
    if (Date.now() - timeOfLastScroll < 3000) {
    requestAnimationFrame(updateProgress);
    requestedAniFrame = true;
    }
    }
    new ResizeObserver(() => {
    bottom =
    document.scrollingElement.scrollTop +
    document.querySelector("#comments,footer").getBoundingClientRect().top;
    winHeight = window.innerHeight;
    scroll();
    }).observe(document.body);
    }
    function expose(name, fn) {
    exposed[name] = fn;
    }
    addEventListener("click", (e) => {
    const handler = e.target.closest("[on-click]");
    if (!handler) {
    return;
    }
    e.preventDefault();
    const name = handler.getAttribute("on-click");
    const fn = exposed[name];
    if (!fn) {
    throw new Error("Unknown handler" + name);
    }
    fn(handler);
    });
    // There is a race condition here if an image loads faster than this JS file. But
    // - that is unlikely
    // - it only means potentially more costly layouts for that image.
    // - And so it isn't worth the querySelectorAll it would cost to synchronously check
    // load state.
    document.body.addEventListener(
    "load",
    (e) => {
    if (e.target.tagName != "IMG") {
    return;
    }
    // Ensure the browser doesn't try to draw the placeholder when the real image is present.
    e.target.style.backgroundImage = "none";
    },
    /* capture */ "true"
    );
    https://kai.im/preloader Danke an Daniel Abromeit @der_abro

    View Slide

  71. Noch nicht genug gehört?
    Lerne einfach alles über
    PageSpeed & Web Vitals
    Melde Dich jetzt unverbindlich
    für mein Online Seminar an!
    https://kai.im/pagespeed

    View Slide