Website Performance

A presentation at JavaScript Days Berlin in October 2023 in Berlin, Germany by Thomas Puppe

Slide 1

Slide 1

Website Performance Thomas Puppe auf den JS Days Berlin 2023

Slide 2

Slide 2

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

Slide 3

Slide 3

Slide 4

Slide 4

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

Slide 5

Slide 5

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

Slide 6

Slide 6

www !== wealthy western web

Slide 7

Slide 7

Slide 8

Slide 8

Slide 9

Slide 9

Website Performance ist ein Wettbewerbsvorteil! https://www.allegisgroup.com/en-gb/insights/blog/2019/december/5-ways-to-gain-a-competitive-advantage-in-your-chosen-field

Slide 10

Slide 10

https://wpostats.com/

Slide 11

Slide 11

Website Performance

Slide 12

Slide 12

Slide 13

Slide 13

TTFB Download Size Asset Count

Slide 14

Slide 14

TTFB Download Size Asset Count window loaded DOM content loaded

Slide 15

Slide 15

TTFB Download Size Asset Count LCP window loaded DOM content loaded CLS INP TTI

Slide 16

Slide 16

LCP CLS DOM content loaded INP window loaded TTFB Asset Download Count Size TTI

Slide 17

Slide 17

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

Slide 18

Slide 18

Drei Säulen von Website Performance A R O

Slide 19

Slide 19

Drei Säulen von Website Performance A R O AVOID REDUCE OPTIMIZE

Slide 20

Slide 20

Drei Säulen von Website Performance A R O AVOID REDUCE OPTIMIZE Benutzen wir alles? Cachen, Ladeverhalten und Brauchen wir alles?​ Komprimieren, Priorisierung. ​Minimieren.

Slide 21

Slide 21

Drei Fünf Säulen von Website Performance A R O M A AVOID REDUCE OPTIMIZE MEASURE ATTITUDE Benutzen wir alles? Cachen, Ladeverhalten und Tooling und Performance Brauchen wir alles?​ Komprimieren, Priorisierung Monitoring​ Culture​ ​Minimieren.

Slide 22

Slide 22

hands-on Workshop-Anteil lama.thomaspuppe.de 🦙 github.com/thomaspuppe/performance-workshop Dein Projekt 🥰 yoursuperawesomepremiumwebsite.com Credits: mage.space, Ales Nesetril auf Unsplash

Slide 23

Slide 23

Drei Fünf Säulen von Website Performance A R O M A AVOID REDUCE OPTIMIZE MEASURE ATTITUDE Benutzen wir alles? Cachen, Ladeverhalten und Tooling und Performance Brauchen wir alles?​ Komprimieren, Priorisierung Monitoring​ Culture​ ​Minimieren.

Slide 24

Slide 24

AVOID

Slide 25

Slide 25

Avoid Stuff: ungenutzte Sachen finden Browser DevTools

Slide 26

Slide 26

Browser Developer Tools Network Tab Filter: domain, larger-than, status-code, priority, … https://developer.chrome.com/docs/devtools/network/reference/​

Slide 27

Slide 27

Avoid Stuff: ungenutzte Sachen finden Browser DevTools Request Maps

Slide 28

Slide 28

Avoid Request Maps • requestmap.webperf.tools ​ • requestmap.pages.dev Gute Visualisierung, wenn die Request-Liste in den DevTools nicht ausreicht. Oder um Stakeholder zu beeindrucken!​

Slide 29

Slide 29

Avoid Request Maps • requestmap.webperf.tools ​ • requestmap.pages.dev Gute Visualisierung, wenn die Request-Liste in den DevTools nicht ausreicht. Oder um Stakeholder zu beeindrucken!​

Slide 30

Slide 30

Avoid Request Maps • requestmap.webperf.tools ​ • requestmap.pages.dev Gute Visualisierung, wenn die Request-Liste in den DevTools nicht ausreicht. Oder um Stakeholder zu beeindrucken!​

Slide 31

Slide 31

Avoid Stuff: ungenutzte Sachen finden Browser DevTools Request Maps Google Tag Manager ausmisten

Slide 32

Slide 32

Avoid Stuff: ungenutzte Sachen finden Browser DevTools Request Maps Google Tag Manager ausmisten Unused CSS/JS via DevTools

Slide 33

Slide 33

Unused CSS/JS

Slide 34

Slide 34

Unused CSS/JS

Slide 35

Slide 35

Unused CSS/JS

Slide 36

Slide 36

Unused CSS/JS

Slide 37

Slide 37

Avoid Code: System Features nutzen

Slide 38

Slide 38

Avoid Code: System Features nutzen System Fonts

Slide 39

Slide 39

Avoid Code System Fonts nutzen Vielleicht kannst du auf Webfonts verzichten. Die System-Schriften auf den Betriebssystemen sind vielfältig. • https://modernfontstacks.com/ • https://gist.github.com/ don1138/5761014 ​ • https://meowni.ca/ font-style-matcher/​

Slide 40

Slide 40

Avoid Code: System Features nutzen System Fonts Dialog / Modal Feature

Slide 41

Slide 41

Credits: Aishwarya Vijay Kumar auf Dribbble

Slide 42

Slide 42

Slide 43

Slide 43

Slide 44

Slide 44

Avoid Code: System Features nutzen System Fonts Dialog / Modal Feature Formular Validierung

Slide 45

Slide 45

Formularvalidierung nativ

Slide 46

Slide 46

Formularvalidierung nativ

Slide 47

Slide 47

Formularvalidierung nativ

Slide 48

Slide 48

Formularvalidierung nativ

Slide 49

Slide 49

Formularvalidierung nativ

Slide 50

Slide 50

Avoid Code: System Features nutzen System Fonts Dialog / Modal Feature Formular Validierung Sharing API

Slide 51

Slide 51

Sharing API

Slide 52

Slide 52

Avoid Code: System Features nutzen System Fonts Dialog / Modal Feature Formular Validierung Sharing API Module/Nomodule fĂĽr JS

Slide 53

Slide 53

Module / Nomodule fĂĽr verschiedene JS Versionen

Slide 54

Slide 54

Avoid Code: System Features nutzen System Fonts Dialog / Modal Feature Formular Validierung Sharing API Module/Nomodule für JS … you get the point!

Slide 55

Slide 55

Drei Fünf Säulen von Website Performance A R O M A AVOID REDUCE OPTIMIZE MEASURE ATTITUDE Benutzen wir alles? Cachen, Ladeverhalten und Tooling und Performance Brauchen wir alles?​ Komprimieren, Priorisierung Monitoring​ Culture​ ​Minimieren.

Slide 56

Slide 56

Reduce

Slide 57

Slide 57

Reduce Caching

Slide 58

Slide 58

Caching und CDN / Proxy Cache​ • deutliches Alarmsignal • wird dir von jedem Testing Tool um die Ohren gehauen • kurze Cache-Zeiten sollten gut begründet sein • immutable nutzen!

Slide 59

Slide 59

Caching und CDN / Proxy Cache​ • deutliches Alarmsignal • wird dir von jedem Testing Tool um die Ohren gehauen • kurze Cache-Zeiten sollten gut begründet sein • immutable nutzen!

Slide 60

Slide 60

Reduce Caching Komprimierung

Slide 61

Slide 61

Komprimierung: gzip, brotli • Gzip als default, drop-in-Lösung ​ • brotli komprimiert 15–30% besser, aber • geringerer Browser-Support (93%) • dynamische Komprimierung dauert länger • Tweaking der 9 gzip und 11 brotli Stufen​

Slide 62

Slide 62

Komprimierung: gzip, brotli • Gzip als default, drop-in-Lösung ​ • brotli komprimiert 15–30% besser, aber • geringerer Browser-Support (93%) • dynamische Komprimierung dauert länger • Tweaking der 9 gzip und 11 brotli Stufen​

Slide 63

Slide 63

Reduce Caching Komprimierung Bildformate

Slide 64

Slide 64

WebP / Avif : Vorteile Größe in kB 680 png jpg 69.7 webp 48 32 avif Größe in kB 46.6 png jpg 24.4 webp avif 5.8 1

Slide 65

Slide 65

WebP / Avif : UnterstĂĽtzung

Slide 66

Slide 66

WebP / Avif : Nutzung

Slide 67

Slide 67

WebP / Avif : Wettbewerbsvorteil!

Slide 68

Slide 68

WebP / Avif : Einsatz Squoosh https://www.smashingmagazine.com/2021/09/modern-image-formats-avif-webp/

Slide 69

Slide 69

Reduce Bildkomprimierung: Testing-Tools​ Lighthouse im Browser oder Web. webspeedtest.cloudinary.com

Slide 70

Slide 70

Bildkomprimierung: …

Slide 71

Slide 71

Bildkomprimierung: SVG! • SVGOptimize • SVGOMG

Slide 72

Slide 72

Reduce Caching Komprimierung Bildformate Responsive Images

Slide 73

Slide 73

Responsive Images Credit: httparchive.org

Slide 74

Slide 74

Responsive Images Credit: httparchive.org

Slide 75

Slide 75

Responsive Images Credit: httparchive.org

Slide 76

Slide 76

Responsive Images Credit: httparchive.org

Slide 77

Slide 77

Responsive Images checken​

Slide 78

Slide 78

Responsive Images checken​

Slide 79

Slide 79

Reduce Responsive Images Checker https://toolsaday.com/seo/ responsive-image-checker

Slide 80

Slide 80

Responsive Images Verwendung 1) Erzeugung https://responsivebreakpoints.com/

Slide 81

Slide 81

Responsive Images Verwendung 1) Erzeugung 2) Einbindung

Slide 82

Slide 82

Bildformate und Responsive Images Bildformat checken: webspeedtest.cloudinary.com Responsive Images checken: toolsaday.com/seo/responsive-image-checker Credit: Pitch Sticker “Cyberpunk”

Slide 83

Slide 83

Reduce Caching Komprimierung Bildformate Responsive Images Schriften: woff2 Format

Slide 84

Slide 84

Schriften: Woff 2 Format 200 198 150 100 61 50 0 ttf Format woff2 Format • Vergesst andere Formate! • Hervorragender Browser-Support • Kompatibilität mit alten Browsern wollen wir nicht.

Slide 85

Slide 85

Reduce Caching Komprimierung Bildformate Responsive Images Schriften: woff2 Format Schriften: Subsetting

Slide 86

Slide 86

Reduce Schriften: Subsetting • https://wakamaifondue.com für Schriften-Eigenschaften​​

Slide 87

Slide 87

Reduce Schriften: Subsetting • https://wakamaifondue.com für Schriften-Eigenschaften​ ​ • https://everythingfonts.com/ subsetter als Subsetting-GUI ​ • https://www.zachleat.com/ web/glyphhanger​als Subsetting-CLI mit UnicodeRange und automatischer Erkennung der Inhalte ​ • https://transfonter.org/​ 200 198 150 100 61 50 0 13 ttf Format woff2 Format woff2 Latin Subset

Slide 88

Slide 88

Webfonts Woff2 und Subsetting • Benutzt du woff2? Und/oder andere Formate? Vergleiche die Größe. https://transfonter.org​​ • Was kann dein Font-File? https://wakamaifondue.com • Erstelle ein passendes Subset. https://everythingfonts.com/subsetter​ Credit: Pitch Sticker “Cyberpunk”

Slide 89

Slide 89

Reduce Caching Komprimierung Bildformate Responsive Images Schriften: woff2 Format Schriften: Subsetting

Slide 90

Slide 90

Fünf Säulen von Website Performance A R O M A AVOID REDUCE OPTIMIZE MEASURE ATTITUDE Benutzen wir alles? Cachen, Ladeverhalten und Tooling und Performance Brauchen wir alles?​ Komprimieren, Priorisierung Monitoring​ Culture​ ​Minimieren.

Slide 91

Slide 91

Pause Credit: Pitch Sticker “Cyberpunk”

Slide 92

Slide 92

Slide 93

Slide 93

Optimize Lazy Loading

Slide 94

Slide 94

Lazy Loading

Slide 95

Slide 95

Lazy Loading via JavaScript​

Slide 96

Slide 96

Lazy Loading via JavaScript​

Slide 97

Slide 97

Lazy Loading via JavaScript​

Slide 98

Slide 98

Lazy Loading via JavaScript​

Slide 99

Slide 99

Lazy Loading nativ Natives Lazyloading im Browser:

Slide 100

Slide 100

Lazy Loading nativ Natives Lazyloading im Browser:

Slide 101

Slide 101

Lazy Loading nativ Natives Lazyloading im Browser:

Slide 102

Slide 102

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

Slide 103

Slide 103

Lazy Loading nativ kein Throttling: 2 Bilder fast 3G: 7 Bilder slow 3G: 16 Bilder

Slide 104

Slide 104

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

Slide 105

Slide 105

Optimize Lazy Loading Fassaden

Slide 106

Slide 106

Fassaden

Slide 107

Slide 107

Fassaden

Slide 108

Slide 108

Fassaden

Slide 109

Slide 109

Fassaden

Slide 110

Slide 110

Fassaden • Videos (youtube/vimeo-lite) • Social Media Widgets • Chats, Support-Messenger • Spiele, Interaktives • Dashboards in Apps • Formular-Logik

Slide 111

Slide 111

Optimize Lazy Loading Fassaden Font Loading

Slide 112

Slide 112

Google Fonts

Slide 113

Slide 113

Google Fonts

Slide 114

Slide 114

Selfhosted Fonts

Slide 115

Slide 115

Optimize Lazy Loading Fassaden Font Loading Font Display

Slide 116

Slide 116

… und während dem Laden der Webfonts?

Slide 117

Slide 117

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

Slide 118

Slide 118

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

Slide 119

Slide 119

font-display Die font-display CSS-Property an @font-face Definitionen gibt dem Browser die Ladestrategie für Webfonts vor.​

Slide 120

Slide 120

font-display Die font-display CSS-Property an @font-face Definitionen gibt dem Browser die Ladestrategie für Webfonts vor.​

Slide 121

Slide 121

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.

Slide 122

Slide 122

Optimize Lazy Loading Fassaden Font Loading Font Display Rel=Preload

Slide 123

Slide 123

Hero-Image

Slide 124

Slide 124

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

Slide 125

Slide 125

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

Slide 126

Slide 126

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. Unterstützt werden nicht nur Bilder, sondern auch Videos, JS Dateien, CSS Dateien.

Slide 127

Slide 127

Hero-Image mit rel=preload

Slide 128

Slide 128

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.-

Slide 129

Slide 129

rel=preload Browser Support

Slide 130

Slide 130

rel=preload und Media Queries, Retina

Slide 131

Slide 131

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 Das funktioniert für HTML-Seiten Bilder, Videos, Styles, JS. Es verbraucht Traffic, 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.

Slide 132

Slide 132

Slide 133

Slide 133

Slide 134

Slide 134

Webfonts Loading und Display • Wann werden die Webfonts geladen?​​ • Wie werden die Webfonts geladen? • Wie ist der Unterschied mit rel=preload und font-display:optional? Credit: Pitch Sticker “Cyberpunk”

Slide 135

Slide 135

Exkurs Local Overrides in den Chrome DevTools • → Settings • → Enable Local Overrides • (Permissions)​ • Inspect Tab • → CSS Source • → ändern und speichern • (HTML und JS ebenso)

Slide 136

Slide 136

Webfonts Loading und Display • Wann werden die Webfonts geladen?​​ • Wie werden die Webfonts geladen? • Wie ist der Unterschied mit rel=preload und font-display:optional? Credit: Pitch Sticker “Cyberpunk”

Slide 137

Slide 137

Optimize Lazy Loading Fassaden Font Loading Font Display Rel=Preload Layout Shift

Slide 138

Slide 138

Layout-Shift​

Slide 139

Slide 139

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/

Slide 140

Slide 140

Cumulative Layout Shift Credit: https://wpostats.com/

Slide 141

Slide 141

Cumulative Layout Shift Credit: https://wpostats.com/

Slide 142

Slide 142

Optimize Layout Shift • Chrome DevTools: • → Console Drawer • → Rendering • → Layout Shift • → Core Web Vitals ​ • Chrome Plugins ​ • https://defaced.dev/tools/ layout-shift-gif-generator/​ ​ • npm install -g layout-shift-gif​ ​ • JS Performance Observer API → Tracking​

Slide 143

Slide 143

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.

Slide 144

Slide 144

Platz freihalten Und wer kennt aspect-ratio? gegen Layout-Shift​ 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.

Slide 145

Slide 145

Platz freihalten Und wer kennt aspect-ratio? gegen Layout-Shift​ aspect-ratio definiert für Box-Elemente automatisch die Höhe anhand der Breite.

Slide 146

Slide 146

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.

Slide 147

Slide 147

Layout Shift • Layout Shift mit den DevTools messen: vorher und nachher​ • Platz für “Hero-Image” oder andere Elemente via aspect-ratio frei halten Credit: Pitch Sticker “Cyberpunk”

Slide 148

Slide 148

Optimize Lazy Loading Fassaden Font Loading Font Display Rel=Preload Layout Shift

Slide 149

Slide 149

Fünf Säulen von Website Performance A R O M A AVOID REDUCE OPTIMIZE MEASURE ATTITUDE Benutzen wir alles? Cachen, Ladeverhalten und Tooling und Performance Brauchen wir alles?​ Komprimieren, Priorisierung Monitoring​ Culture​ ​Minimieren.

Slide 150

Slide 150

Pause Credit: Pitch Sticker “Cyberpunk”

Slide 151

Slide 151

Measure

Slide 152

Slide 152

Measure DevTools

Slide 153

Slide 153

Measure DevTools • Throttling • Local Source Overrides • Web Vitals Score • Layout Shift • Unused CSS/JS ​ • JavaScript: Memory, Frame Rate,​CPU Flame Graphs

Slide 154

Slide 154

Measure DevTools • Throttling • Local Source Overrides • Web Vitals Score • Layout Shift • Unused CSS/JS ​ • JavaScript: Memory, Frame Rate,​CPU Flame Graphs devtoolstips.org

Slide 155

Slide 155

Measure DevTools Lighthouse

Slide 156

Slide 156

Measure Lighthouse • DevTools ​ • CLI npm install -g lighthouse​ ​ • npx lightouse

Slide 157

Slide 157

Measure DevTools Lighthouse Page Speed Insights

Slide 158

Slide 158

Measure Pagespeed Insights pagespeed.web.dev

Slide 159

Slide 159

Measure DevTools Lighthouse Page Speed Insights Webpagetest

Slide 160

Slide 160

Measure Webpagetest webpagetest.org

Slide 161

Slide 161

Measure Webpagetest webpagetest.org und perfproxy.com zum Erzeugen von mehr Experimenten​

Slide 162

Slide 162

Measure DevTools Lighthouse Page Speed Insights Webpagetest Speedcurve

Slide 163

Slide 163

Measure Speedcurve speedcurve.com

Slide 164

Slide 164

Measure DevTools Lighthouse Page Speed Insights Webpagetest Speedcurve CrUX

Slide 165

Slide 165

Measure CrUX developer.chrome.com/ docs/crux/dashboard/

Slide 166

Slide 166

Fünf Säulen von Website Performance A R O M A AVOID REDUCE OPTIMIZE MEASURE ATTITUDE Benutzen wir alles? Cachen, Ladeverhalten und Tooling und Performance Brauchen wir alles?​ Komprimieren, Priorisierung Monitoring​ Culture​ ​Minimieren.

Slide 167

Slide 167

Attitude

Slide 168

Slide 168

Slide 169

Slide 169

Attitude Regression vermeiden

Slide 170

Slide 170

Regression vermeiden • Permanentes Monitoring • Performance Budgets • synthetisch • npm Pakete • ggf RUM • CSS Output • monatliche CrUX Reports • Alerts von Speedcurve, Webpagetest, …

Slide 171

Slide 171

Attitude Regression vermeiden Performance Culture

Slide 172

Slide 172

Performance Culture • Buy-In von der Chefetage • Zahlen • Dashboards • Benchmarking !

Slide 173

Slide 173

Performance Culture • Buy-In von der Chefetage • Zahlen • Dashboards • Benchmarking !

Slide 174

Slide 174

Performance Culture • Buy-In von der Chefetage • Performance als Feature • Zahlen • in NFRs aufnehmen • Dashboards • BUG-Tickets schreiben • Benchmarking !

Slide 175

Slide 175

Attitude Regression vermeiden Performance Culture Up-to-date bleiben

Slide 176

Slide 176

Up-to-date bleiben • web.dev/fast • github.com/davidsonfellipe/awesome-wpo • www.smashingmagazine.com/category/performance/ • perfplanet.com ​ • calibreapp.com/blog • speedcurve.com/blog • debugbear.com/blog ​ • simonhearne.com/posts • csswizardry.com/archive • timkadlec.com/remembers

Slide 177

Slide 177

Dankeschön ❤️

Slide 178

Slide 178

Dankeschön ❤️ Thomas is hiring @ ZEIT Online: dev.zeit.de

Slide 179

Slide 179

Dankeschön ❤️ Thomas is hiring @ ZEIT Online: dev.zeit.de www.thomaspuppe.de ​https://webperf.social/@thomaspuppe