Trainer München Thomas Puppe 22. März 2023 Workshop @ JS Days München 2023 Website Performance

👋 Hi, ich bin Thomas Senior Frontend Developer bei ZEIT Online. #webperf #a11y #leanweb​

Website Performance

Credit: httparchive.org

Credits: https://de.statista.com/infografik/29079/durchschnittliche-kosten-fuer-1-gb-datenvolumen-in-ausgewaehlten-laendern-regionen/ , https://de.statista.com/infografik/24774/anteil-der-befragten-nach-der-groesse-des-inklusiven-datenvolumens/​

Credit (left to right): Anastasia Nelen auf Unsplash

Credit: Pawel Czerwinski auf Unsplash

“According to Google’s DoubleClick, when comparing sites that load in 5 seconds to sites that load in 19 seconds, the faster sites had 70% longer average session lengths, 35% lower bounce rates and 25% higher ad viewability than their slower counterparts.” – wpostats.com

“Rebuilding Pinterest pages for performance resulted in a 40% decrease in wait time, a 15% increase in SEO traffic and a 15% increase in conversion rate to signup.” – wpostats.com

“SpeedSense worked with an e-commerce company to improve performance and saw a 7.6% increase in sitewide conversion, translating to roughly a $6 million lift in annual revenue. Mobile transactions increased by nearly 30% and sales per session increased by 16%.” – wpostats.com

“Rakuten 24 ran an A/B test showing: improved vitals brought a 53.4% incrase in revenue per visitor, 33.1% increase in conversion rate, 15.2% increase in average order value, 35.1% reduction in exit rate and more!” – wpostats.com

Credit: wpostats.com

Credit: Markus Spiske auf Unsplash

Website 😻 Performance

Aspekte von Aus Usersicht Website schnell / schlank / ruckelt nicht Performance Browser / Technologien HTML / CSS / Bilder / JavaScript / Schriften / Video / Audio Build / Server Bildformate / Komprimierung / CDN, Cloud / Caching / Netzwerk Wirkung Objektive Zahlen / Subjektive Wahrnehmung Kontrolle Messung / Testing / Monitoring / SEO Einfluss

Aspekte von Aus Usersicht Website schnell / schlank / ruckelt nicht Performance Browser / Technologien HTML / CSS / Bilder / JavaScript / Schriften / Video / Audio Build / Server Bildformate / Komprimierung / CDN, Cloud / Caching / Netzwerk Wirkung Objektive Zahlen / Subjektive Wahrnehmung Kontrolle Messung / Testing / Monitoring / SEO Einfluss

Her mit dem Code !

lama.thomaspuppe.de

Los gehts ! https://lama.thomaspuppe.de/notes.html 1– Wir setzen eine lokale Kopie auf unserem eigenen Rechner auf. 2– lokal öffnen, oder lokaler Webserver, oder Netlify/Vercel 3– Debugging mit dem Chrome Browser

erster Überblick

Devtools im Browser Der Webbrowser mit seinen Developer Tools ist das allerbeste Werkzeug für Web-Developer.

Alarmsignale: • Caching • Komprimierung

Bildoptimierung Größe in MB 55 Original 14.9 Breite 1000px Optimierte PNG 3.5 WEBP 0.867

Bildoptimierung Bildoptimierung, schnell und simpel mit Node Modulen. Originalbilder 55,5 MB npx image-cli-tools ./images/.png maxwidth=1000 npx image-cli-tools ./images/.png -o npx image-cli-tools ./images/*.png -webp Quasi jedes Tool lässt sich manuell aufrufen oder in den Build-Prozess integrieren. Außerdem gibt es kostenlose Web-Services und Applications mit GUI. Das gilt selbst für SVGs (SVGOptimize).

Takeaway Absolute Basics: - Bildkomprimierung beim Build - Datentransfer mit gzip / brotli - Caching

WebP Browser Support

WebP Fallback Einbindung mit Fallback für ältere Browser: <picture> <source srcset=”hero.webp” type=”image/webp”> <source srcset=”hero.png” type=”image/png”> <img src=”hero.jpg” alt=”Lamas!”> </picture> Responsive Bilder und Retina lassen wir heute außen vor.

BildOptimierung Coding Time ☐ Bildpfade ändern von images_unoptimized zu images_optimized Credit: Pitch Sticker “Cyberpunk”

Credits: apple.com, Lee Campbell auf Unsplash, Shiwa ID auf Unsplash

Browser Network Throttling Chromium und Firefox haben in den Devtools die Funktion, eine langsamere Netzwerkverbindung zu simulieren und das Caching auszuschalten.

Credits: Walt Disney Animation Studios / Giphy

Takeaway 80% der Performance-relevanten Beobachtungen mache ich im Netzwerk-Panel der Browser Developer Tools.

Was wird wann geladen?

Hero-Image

Die Spalten im Netzwerk-Tab der Developer Tools lassen sich anpassen. So kann man zum Beispiel den Initiator von Requests anzeigen.

Critical Rendering Path im Browser Credit: https://www.youtube.com/watch?v=ufCVTowBxoY

Preload​ Mit Preload-Links können wir im Head einer HTML-Seite dem Browser schon Hinweise geben auf Ressourcen, die während dem Rendern gebraucht werden.

<head> <link rel=”preload” as=”image” href=”/images_optimized/png/hero.png”> {… CSS usw usf …} </head> <body> … Unterstützt werden nicht nur Bilder, sondern auch Videos, JS Dateien, CSS Dateien.

Preload Coding Time ☐ Gib dem Browser das Hero-Image schon im HTMLHead bekannt

<link rel=”preload” as=”image” href=”/images_optimized/png/hero.png”> Credit: Pitch Sticker “Cyberpunk”

Hero-Image mit rel=preload

Developer Tools:​ Resource Priority Im Netzwerk-Tab kann man mit der rechten Maustaste die dargestellten Spalten umstellen. Eine davon ist die Priority. Sie zeigt an, ob der Browser dieselbe Vorstellung von Resource Priority hat wie ihr.-

rel=preload Browser Support

rel=preload und Media Queries, Retina

<link rel=”preload” as=”image” href=”hero-narrow.png” media=”(max-width: 600px)” > <link rel=”preload” as=”image” href=”/images/hero-huge_2x.png” media=”(min-width: 900px) and (-webkit-mindevice-pixel-ratio: 2)”> <link rel=”preload” as=”image” href=”hero.jpg” imagesrcset=”hero_800px.jpg 800w, hero_1600px.jpg 1600w” imagesizes=”50vw”> <link rel=”preload” as=”image” imagesrcset=”hero.png 1x, hero-2x.png 2x”>

Takeaway Bilder und andere Ressourcen, die im ersten Viewport gezeigt werden, aber nicht im HTML vom Browser gefunden werden, per rel=preload im Head vorladen!

Während Preload Ressourcen auf der aktuellen Seite priorisiert, können mit Prefetch Inhalte vorgeladen werden, die auf späteren Seiten benötigt werden. Prefetch <link rel=”prefetch” as=”image” href=”/images/checkout-hero.jpg” /> <link rel=”prefetch” as=”document” href=”next-step.html” /> Das funktioniert für HTML-Seiten Bilder, Videos, Styles, JS. Es verbraucht Datenverkehr, sollte also bewusst und gezielt eingesetzt werden. User können es in den Browser-Settings unterbinden. “Quicklink” und “Guess” sind JavaScript Bibliotheken, die das Prefetchen automatisieren.

Lazy Loading

Lazy Loading Große Ressourcen sollten erst geladen werden, wenn sie tatsächlich gebraucht werden. Zum Beispiel: Bilder erst beim Scrollen auf der Seite laden.

Lazy Loading

Lazy Loading via JavaScript​ Für eine einfache Lazyload Implementierung reicht aus: <img data-src=”hero.png” alt=”Lamas!” > Dieses JavaScript tauscht die Bilder aus, sobald sie in den Viewport kommen: const images = document.querySelectorAll(‘img[data-src]’); const options = { rootMargin: ‘0px’, threshold: 0.5 }; const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const image = entry.target; const src = image.getAttribute(‘data-src’); image.setAttribute(‘src’, src); image.removeAttribute(‘data-src’); observer.unobserve(image); } }); }, options); images.forEach(image => { observer.observe(image); });

Lazy Loading Für eine einfache Lazyload Implementierung reicht aus: <img data-src=”hero.png” alt=”Lamas!” > via JavaScript​ Dieses JavaScript tauscht die Bilder aus, sobald sie in den Viewport kommen: const images = document.querySelectorAll(‘img[data-src]’); const options = { rootMargin: ‘0px’, threshold: 0.5 }; const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const image = entry.target; const src = image.getAttribute(‘data-src’); image.setAttribute(‘src’, src); image.removeAttribute(‘data-src’); observer.unobserve(image); } }); }, options); images.forEach(image => { observer.observe(image); });

Lazy Loading Für eine einfache Lazyload Implementierung reicht aus: <img data-src=”hero.png” alt=”Lamas!” > via JavaScript​ Dieses JavaScript tauscht die Bilder aus, sobald sie in den Viewport kommen: const images = document.querySelectorAll(‘img[data-src]’); const options = { rootMargin: ‘0px’, threshold: 0.5 }; const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const image = entry.target; const src = image.getAttribute(‘data-src’); image.setAttribute(‘src’, src); image.removeAttribute(‘data-src’); observer.unobserve(image); } }); }, options); images.forEach(image => { observer.observe(image); });

Lazy Loading Für eine einfache Lazyload Implementierung reicht aus: <img data-src=”hero.png” alt=”Lamas!” > via JavaScript​ Dieses JavaScript tauscht die Bilder aus, sobald sie in den Viewport kommen: const images = document.querySelectorAll(‘img[data-src]’); const options = { rootMargin: ‘0px’, threshold: 0.5 }; const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const image = entry.target; const src = image.getAttribute(‘data-src’); image.setAttribute(‘src’, src); image.removeAttribute(‘data-src’); observer.unobserve(image); } }); }, options); images.forEach(image => { observer.observe(image); });

Lazy Loading nativ Natives Lazyloading im Browser: <img src=”hero.png” alt=”Lamas!” loading=”lazy” >

Lazy Loading nativ Natives Lazyloading im Browser: <img src=”hero.png” alt=”Lamas!” loading=”lazy” >

<iframe src=”datawrapper.html” loading=”lazy” >

Lazy Loading nativ Natives Lazyloading im Browser: <img src=”hero.png” alt=”Lamas!” loading=”lazy” >

loading=lazy Verbreitung: 25% der Seiten im Netz nutzen das loading=lazy Attribut an Bildern. Credit: https://httparchive.org/reports/state-of-images#imgLazy

Lazy Loading Mit loading=lazy übergibt man die Kontrolle an den Browser. Und der macht vielleicht Dinge, die man nicht möchte. nativ Zum Beispiel wird mehr vorgeladen, wenn die Internetverbindung langsam ist! kein Throttling: 2 Bilder fast 3G: 7 Bilder slow 3G: 16 Bilder

Lazy Loading Coding Time ☐ Implementiere Lazy Loading mit data-src und js/lazyload.js — oder —​ ☐ Implementiere Lazy Loading mit load=lazy Credit: Pitch Sticker “Cyberpunk”

Pause Credit: Pitch Sticker “Cyberpunk”

Layout Shift

Layout-Shift​

Cumulative Der Cumulative Layout Shift (CLS) ist eine Maßeinheit für unerwartetes Verschieben des Layouts einer Website. Layout Shift CLS ist einer der Core Web Vitals von Google und fließt mit in das Google-Ranking ein! Credit: https://web.dev/cls/

Platz freihalten gegen Wer kennt den Padding-Trick? .image-container { position: relative; Layout-Shift​ padding-bottom: 56.25%; /* 16:9 Format, 9/16*100 */ } .image-container img { position: absolute; } Der Container des Bildes bekommt einen Padding-Bottom entsprechend des Bildverhältnisses. Das funktioniert, weil sich ein prozentuales Padding an der Breite des Containers orientiert. In den entsprechend dimensionierten Container passt das Bild (absolut positioniert, um nicht unter dem Padding zu landen) genau rein.

Platz freihalten gegen Layout-Shift​ Und wer kennt aspect-ratio? .img { aspect-ratio: 1.777; /* aspect-ratio: 16/9; */ } aspect-ratio definiert für Box-Elemente automatisch die Höhe anhand der Breite. Der Wert ist eine Dezimalzahl, die man aber auch durch einen Bruch angeben kann. Dieser wiederum nimmt auch die width/height Attribute eines Bildes entgegen.

Platz freihalten Und wer kennt aspect-ratio? gegen .img { Layout-Shift​ } aspect-ratio: 16/9; aspect-ratio definiert für Box-Elemente automatisch die Höhe anhand der Breite.

Cumulative Layout Shift Coding Time ☐ Binde das Hero-Image als Figure ein (statt als Hintergrundbild) und lade die kleinere CSS-Datei statt “styles-large.css”. ​ ☐ Definiere eine aspect-ratio von 1.777 für die Bilder ☐ Beobachte den Layout Shift (vorher und) nachher. ​ ☐ ggf Lazy Loading​ Credit: Pitch Sticker “Cyberpunk”

Takeaway Elemente, deren Höhe der Browser noch nicht kennt (aber ihr) mit aspect-ratio freihalten lassen, um Layout Shift zu vermeiden.

Core Web Vitals Web Vitals sind Metriken, die Google als zentrale Werte für die Performanve von Websites ermittelt. Diese Werte fließen ins Page Ranking mit ein. • LCP (Largest Contentful Paint): Zeit vom Klick auf einen Link bis zum Rendern des größten Teils des Inhalts. • CLS (Cumulative Layout Shift): optische Instabilität der Seite, gemessen aus Positionsverschiebungen von Elementen. • FID (First Input Delay): Verzögerung zwischen der ersten Interaktion mit er Seite, und einer Reaktion.

Pause Credit: Pitch Sticker “Cyberpunk”

Font Loading

Google Fonts @import url(‘https://fonts.googleapis.com/css2? family=Montserrat’); h1 { font-family: ‘Montserrat’; }

Google Fonts

<head> <link rel=”preconnect” href=”https://fonts.googleapis.com”> <link rel=”preconnect” href=”https://fonts.gstatic.com” crossorigin> <link href=”https://fonts.googleapis.com/css2? family=Montserrat” rel=”stylesheet”>

Selfhosted @font-face { font-family: ‘Montserrat’; Fonts font-style: normal; font-weight: 400; font-display: block; src: url(‘/fonts/Montserrat-Regular.woff2’) format(‘woff2’); } h1 { font-family: ‘Montserrat’; }

<link href=”/fonts/Montserrat-Regular.woff2” rel=”preload” as=”font” crossorigin>

Exkurs: Größe von Webfonts reduzieren 01 02 woff2 als Format verwenden Subsetting auf die benötigten Glyphen https://cloudconvert.com/ttf-to-woff2 https://everythingfonts.com/subsetter https://www.zachleat.com/web/glyphhanger/ 198 200 150 100 61 50 13 0 ttf Format woff2 Format woff2 Latin Subset 🤩

Font Preload​ Coding Time ☐ Optimiere die Einbindung der Schrift: ​ ☐ Self Hosting (lokale “MontserratLocal” verwenden) ​ ☐ kurzer “Critical Rendering Path” mit rel=preload ​ ​ ☐ Achtung: Google Font entfernen.​ Credit: Pitch Sticker “Cyberpunk”

Takeaway Schriften im woff2 Format selbst hosten und im HTML Head mit einem rel=preload ankündigen! Pro-Tip: Font Subsetting! ​

Font Loading / Display

… und während dem Laden der Webfonts?

… und während dem Laden der Webfonts? Credit: Zach Leatherman: The Mitt Romney webfont problem

Credits: https://www.fasterize.com/en/blog/web-performance-optimising-loading/

font-display Die font-display CSS-Property an @font-face Definitionen gibt dem Browser die Ladestrategie für Webfonts vor.​ @font-face { font-family: ‘MyWebFont’; src: url(‘myfont.woff2’) format(‘woff2’); font-display: [auto|block|swap|fallback|optional]; }

font-display Die font-display CSS-Property an @font-face Definitionen gibt dem Browser die Ladestrategie für Webfonts vor.​ @font-face { font-family: ‘MyWebFont’; src: url(‘myfont.woff2’) format(‘woff2’); font-display: [auto|block|swap|fallback|optional]; } Credit: https://caniuse.com/css-font-rendering-controls

font-display font-display: block; font-display: swap; font-display: fallback; font-display: optional; block swap fallback optional Platz wird freigehalten, System-Font wird Platz wird kurz freigehalten, Wie Fallback, aber der bis die Webfont angezeigt, bis die dann wird Systemfont Browser darf die Webfont geladen ist. Webfont geladen ist. gezeigt, dann die Webfont auch weglassen bei (wenn binnen 3s geladen). langsamen Verbindungen.​ Beim nächsten Seitenaufruf Beim nächsten Seitenaufruf ist die Schrift dann da. ist die Schrift dann da. FOIT FOUT (flash of invisible text) (flash of unstyled text) auto ist der Browser-Default, und das ist in der Regel swap/fallback. Swap wird auch von Google Fonts mitgegeben.

font-display Coding Time ☐ Benutze die langsame ‘MySlowWebfont” auf unserer Testseite. ​ ☐ Beobachte und ändere die Font Loading Strategie ​ ☐ Welche Strategie ist am besten gegen Layout Shift? Credit: Pitch Sticker “Cyberpunk”

Tooltipp Langsame Verbindungen simulieren mit • https://slowfil.es/ • https://www.npmjs.com/package/deelay Timeouts simulieren mit • https://blackhole.webpagetest.org • Blackhole-IP in die /etc/hosts eintragen: 72.66.115.13 www.google-analytics.com

Exkurs: Bei font-display: swap/fallback gibt es einen Flash of Unstyled Text (FOUT). Optimierung der Fallback Systemschrift Durch die unterschiedliche Laufweite und Buchstaben-Höhe von Systemschrift und Webfont springt der Text beim Laden der Webfont.

Exkurs: Bei font-display: swap/fallback gibt es einen Flash of Unstyled Text (FOUT). Optimierung der Fallback Systemschrift Mit dem Font Style Matcher von Monica Dinculescu kann man seine Fallbackfont per CSS so tweaken, dass der Flash of Unstyled Text möglichst unauffällig ist.

Vielleicht kannst du ganz auf Webfonts verzichten. Die Standard-Schriften der Betriebssysteme sind vielfältig. System Font Stacks • https://modernfontstacks.com/ • https://gist.github.com/don1138/5761014

Takeaway

  • Webfont benötigt? - Schriften im woff2 Format selbst hosten - im Head mit einem rel=preload ankündigen - Ladestrategie via font-display​

Performance Measuring Tools

Developer Tools:​ Code Coverage https://devtoolstips.org

Lighthouse Google Lighthouse ist ein kostenloses Open-Source-Tool von Google, das Webentwicklern dabei hilft, die Leistung, Zugänglichkeit, Best Practices und Suchmaschinenoptimierung (SEO) ihrer Websites zu bewerten und zu verbessern. Lighthouse führt automatisch eine Reihe von Tests durch, um festzustellen, wie gut eine Website in diesen Bereichen abschneidet, und gibt dann Empfehlungen zur Verbesserung der Ergebnisse aus. • in den Browser Devtools • CLI • 🎯 npm install -g lighthouse) npx lighthouse ( http://localhost:4321/index.html • Pagespeed Insights Website https://pagespeed.web.dev/

Webpagetest .org 🥰 Bestes Tool zur manuellen Überprüfung. Bietet gute Übersicht für Einsteiger, und eine Menge Profi-Features. ​ Gratis-Account verfügbar.

Speedcurve Bestes Tool für kontinuierliches Monitoring. Bietet neben synthetischen Tests auch Real User Monitoring. .com​ Nur Bezahl-Accounts, startet bei 12$ pro Monat.

🚀 Quellen zum Reinnerden ins Thema • web.dev/fast , awesome-wpo , • Blogs von CalibreApp , Harry Roberts , Tim Kadlec , Smashing Magazine , DebugBear , perfplanet.com • perf-tooling.today

🚀 Dankeschön​ https://www.thomaspuppe.de https://webperf.social/@thomaspuppe​

Timing verpeilt? ​ 1– Witzige Lama-Bilder generieren 2– Was fiel euch noch auf auf der Lama-Website? 3– Eine Website eurer Wahl analysieren 4– Fragen oder freie Diskussion zu Website Performance 5– fetchpriority, Responsive Images, JS/CSS Async Loading