Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ladezeitenoptimierung für SEOs: PageSpeed Extre...

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. 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
  2. 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
  3. 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)
  4. 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
  5. 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 <html> <body> <h1>Hello, World!</h1> </body> </html>
  6. 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 <html> <body> <h1>Hello, World!</h1> </body> </html>
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. Also besser so… CSS-Datei herunterladen CSS prozessieren WebFont herunterladen WebFont

    rendern Text anzeigen HTML geladen https://web.dev/font-display/
  13. 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
  14. 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
  15. 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