Slide 1
@zachleat
@zachleat @zachleat.com @Anvil transition enthusiast
Slide 2
WHYs THE 5 WHYs OF WEB WHYs LOADIN WHYs PERFOR WHYs
Slide 3
WHYs WHYs OF WEB FONT WHYs LOADING WHYs PERFORMANCE WHYs
Slide 4
@zachleat
HY WHY WHY WHY W HY WHY WHY WHY W HY WHY WHY WHY W HY WHY WHY WHY W HY WHY WHY WHY W
Slide 5
@zachleat
WHY WHY WHY WHY YWHY WHY WHY WHY WHY WHY WHY WHY WHY YWHY WHY WHY WHY WHY WHY WHY WHY WHY YWHY WHY WHY WHY WHY WHY WHY WHY WHY YWHY WHY WHY WHY WHY WHY WHY WHY WHY YWHY WHY WHY WHY WHY
Slide 6
Y THE 5Y OF WEB FONT Y LOADING Y PERFORMANCE Y
Slide 7
THE DEFAULT Wordpress Site
Slide 8
THE DEFAULT Wordpress Site
595 KB 35 requests
Slide 9
17% WEB Fonts 100 KB in 5 requests
YYYYY
48% Images, 8 requests 22% JavaScript, 12 requests 17% Fonts, 5 requests 12% CSS, 8 requests 1% HTML, 2 requests
Slide 10
Slide 11
YY
SANS SERIF BOLD
15.3 KB
Slide 12
Slide 13
YYYY 20.8 KB
SERIF ITALIC
Slide 14
YYYY Y 26.2 KB
SERIF BOLD
Slide 15
All demos on GitHub https://github.com/zachleat/performance-sometime
Slide 16
https://www.webpagetest.org/
METHODOLOGY 3G Network Speed HTTP/2 and HTTPS CHROME & WOFF2 ONLY FONT OPTIMIZATIONS @zachleat
Slide 17
THE default Wordpress Site
SERIF SANS-SERIF BOLD SERIF BOLD SERIF ITALIC SANS-SERIF first render 3.3s
visually complete
5.7s
Slide 18
OUR OPPONENTS: INVISIBLE TEXT TEXT IN MOTION
Slide 19
OUR OPPONENTS: INVISIBLE TEXT FOIT TEXT IN MOTION
Slide 20
@zachleat
https://twitter.com/jmuspratt/status/561239961924403200
Slide 21
OUR OPPONENTS: INVISIBLE TEXT TEXT IN MOTION FOUT
Slide 22
CRITICAL REQUEST CHAINS DOMCONTENTLOADED FIRST CONTENTFUL PAINT FIRST PAINT
PERFORMANCE METRICS
FIRST RENDER
VISUALLY COMPLETE SPEED INDEX ONLOAD TIME TO INTERACTIVE CPU IDLE
Slide 23
FIRST RENDER FIRST CONTENTFUL PAINT
Slide 24
FIRST MEANINGFUL PAINT Finally a metric that PROPERLY accounts for web fonts 🎉
MEASURE using LIGHTHOUSE
Slide 25
OPPONENTS: INVISIBLE TEXT TEXT IN MOTION
NEW METRIC:
ALL TEXT VISIBLE
Slide 26
THE default Wordpress Site ALL TEXT VISIBLE
first render 3.3s
👀
4.9s
visually complete
5.7s
Slide 27
OPPONENTS: INVISIBLE TEXT TEXT IN MOTION
NEW METRIC:
WEB FONT REFLOW COUNT * After first render
Slide 28
REFLOW COUNTER
0
@zachleat
Slide 29
REFLOW COUNTER
10
@zachleat
Slide 30
REFLOW COUNTER
21
@zachleat
Slide 31
REFLOW COUNTER
32
@zachleat
Slide 32
REFLOW COUNTER
43
@zachleat
Slide 33
REFLOW COUNTER
54
@zachleat
Slide 34
REFLOW COUNTER
65
@zachleat
Slide 35
RE F RE LO FLO W W RE F R L E RE FL OW FLO OW W
THE default Wordpress Site
first render 3.3s
visually complete
5.7s
Slide 36
OUR METRICS:
ALL TEXT VISIBLE WEB FONT REFLOW COUNT
Slide 37
Slide 38
YYYYY “WEB-SAFE”/SYSTEM/INSTALLED FONTS
Slide 39
YYYYY
System fonts
System Fonts: Baseline:
▼
-6% 3.1s first render 3.3s
▼
-10% 5.1s visually complete 5.7s
Slide 40
YYYYY System fonts
No network requests INSTANT RENDERING @zachleat
Slide 41
@zachleat
THANK YOU
@zachleat @zachleat.com
Slide 42
Slide 43
Slide 44
BEST VIEWED @zachleat
IN CHROME
Slide 45
@zachleat
https://github.com/alrra/browser-logos
Slide 46
Slide 47
THE default Wordpress Site
first render 3.3s
visually complete
5.7s
Slide 48
Slide 49
OUR TOOLS: WOFF2 PRECONNECT SELF HOSTING SHARDING 😱
FONT-DISPLAY PRELOAD CSS FONT LOADING API SUBSETTING VARIABLE FONTS
Slide 50
Slide 51
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin>
Slide 52
<!-- CSS --> <link rel='dns-prefetch' href='//fonts.googleapis.com'> <!-- Fonts --> <link rel='preconnect' href='https://fonts.gstatic.com' crossorigin> <link rel='alternate' …> <link rel='alternate' …> <script>…</script> <script>…</script> <style>…</style> <link rel='stylesheet' …> <link rel='stylesheet' href=' https://fonts.googleapis.com/css?family= Noto Sans:400italic,700italic,400,700| Noto Serif:400italic,700italic,400,700| Inconsolata:400,700&subset=latin,latin-ext'>
Slide 53
PRECONNECT 🎉 WITHOUT
CSS
WITH
FONTS
@zachleat
Slide 54
Preconnect Browser SUPPORT
https://caniuse.com/#feat=link-rel-preconnect
Slide 55
PRECONNECT:
GREAT FOR CROSS-ORIGIN FONT REQUESTS @zachleat
Slide 56
OUR TOOLS: WOFF2 PRECONNECT SELF HOSTING SHARDING 😱
FONT-DISPLAY PRELOAD CSS FONT LOADING API SUBSETTING VARIABLE FONTS
Slide 57
YYYYY THIRD PARTY ▸ SELF HOSTING
Slide 58
YYYYY
SELF HOSTING BASE LINE ▼
👀
Self Hosting: Baseline:
▼
-6% 3.1s first render 3.3s
▼
-1% 5.6s
visually complete 5.7s
Slide 59
WHAT HAPPENED?
SUPER LONG TTFB’S NETWORK CONGESTION BAD HTTP/2 prioritiZATION @zachleat
Read more: https://blog.cloudflare.com/http-2-prioritization-with-nginx/
Slide 60
@font-face { src: url(notosans.woff2) format('woff2'); } ▼ @font-face { src: url(https://performance-sometimeassets.netlify.com/notosans.woff2) format('woff2'); }
Slide 61
YYYYY
SELF HOSTING SELF HOST ▼
👀
Self Hosting: Baseline:
▼
-6% 3.1s first render 3.3s
▼
-1% 5.6s
visually complete 5.7s
Slide 62
YYYYY
SELF HOSTING
WITH A BIT OF SHARDING USING PRECONNECT
👀
Self Host & Shard:
Baseline:
▼
-6% 3.1s first render 3.3s
5.7s visually complete 5.7s
Slide 63
***DON’T DO THIS, PROBABLY SHARDING IS AN ANTI-PATTERN ON HTTP/2 @zachleat
Slide 64
“ ONE PERSON’S TRASH IS ANOTHER PERSON’S -PATTERN TREASURE” ” ANTI-PATTERN
Slide 65
Slide 66
WHY SELF HOST?
HOLD YOUR HORSES ⭐⭐⭐⭐🐴 @zachleat
Slide 67
OUR TOOLS: WOFF2 PRECONNECT SELF HOSTING SHARDING 😱
FONT-DISPLAY PRELOAD CSS FONT LOADING API SUBSETTING VARIABLE FONTS
Slide 68
Slide 69
@font-face { font-display: swap; }
Shows Fallback Font Immediately, RENDER WEB FONT WHENEVER @zachleat
Learn more: https://font-display.glitch.me/
Slide 70
@font-face { font-display: optional; }
RENDER WEB FONT ONLY IF CACHED @zachleat
Learn more: https://font-display.glitch.me/
Slide 71
font-display Browser SUPPORT
https://caniuse.com/#feat=css-font-rendering-controls
Slide 72
font-display Browser SUPPORT
https://caniuse.com/#feat=css-font-rendering-controls
Slide 73
font-display: swap -ish
@zachleat
Slide 74
WE NO LONGER NEED JavaScript to load a WEB FONT *WITH VISIBLE FALLBACK TEXT
@zachleat
Slide 75
YYYYY
SELF HOSTING
WITH A BIT OF SHARDING USING PRECONNECT
BASE LINE ▼
AND Font-DISPLAY
👀
New:
Baseline:
▼
-3% 3.2s first render 3.3s
5.7s visually complete 5.7s
Slide 76
OUR OPPONENTS: INVISIBLE TEXT TEXT IN MOTION
Slide 77
OUR TOOLS: WOFF2 PRECONNECT SELF HOSTING SHARDING 😱
FONT-DISPLAY PRELOAD CSS FONT LOADING API SUBSETTING VARIABLE FONTS
Slide 78
Slide 79
<link rel="preload" href="notosans.woff2" as="font" type="font/woff2" crossorigin>
Slide 80
PRELOAD BROWSER SUPPORT
https://caniuse.com/#feat=link-rel-preload
Slide 81
YYYYY
SELF HOSTING
WITH A BIT OF SHARDING USING PRECONNECT
BASE LINE ▼
AND Font-DISPLAY AND PRELOAD
👀
⏰ New:
3.3s
▲ 3% 5.9s
Baseline:
first render 3.3s
visually complete 5.7s
Slide 82
PRELOADING fonts FROM A DIFFERENT ORIGIN INCURS CONNECTION COSTS AT A BAD TIME ⚠ @zachleat
Slide 83
YYYYY
SELF HOSTING
WITH A BIT OF SHARDING AND Font-DISPLAY AND PRELOAD
BASE LINE ▼
👀
🗑 New:
Baseline:
▲ 15% 3.8s first render 3.3s
▼
-1% 5.6s
visually complete 5.7s
Slide 84
OVERUSE OF PRELOAD WILL COST YOU in FIRST RENDER TIME ⚠ @zachleat
Slide 85
FIRST RENDER
PRELOAD
PRELOAD
@zachleat
PRELOAD
Slide 86
PRELOAD SOME, NOT ALL. HOW TO CHOOSE? @zachleat
Slide 87
Slide 88
PRIORIZATION STRATEGY:
USER DISRUPTION METRICS @zachleat
Slide 89
Y
USER DISRUPTION
Y
Y Y Y
PRIORIZATION
YYYYY
Y Y Y
@zachleat
Y
Slide 90
What reflows are most likely to BE THE MOST DISRUPTIVE? @zachleat
Slide 91
Y
USER DISRUPTION
Y
Y Y Y
PRIORIZATION
YYYYY
Y Y Y
@zachleat
Y
Slide 92
METRICS
PRIORIZATION: PRELOAD ONE OF EACH FAMILY
@zachleat
YY YYY
Slide 93
Y
METRICS
PRIORIZATION: PRELOAD ONE OF EACH FAMILY
Y
Y
YY YYY Y
@zachleat
❤
Slide 94
ROMAN
FALLBACK
FAUX-BOLD
FONT-SYNTHESIS
❤
BOLD 🏁 @zachleat
Slide 95
FONT-SYNTHESIS
FALLBACK
Y
@zachleat
🚫
Y
Slide 96
DEAR WEB BROWSERS, CAN YOU COPY WEBKIT Please? NON-WEBKIT
IT’S ME, MARGARET
❤
FONT-SYNTHESIS
Slide 97
OUR TOOLS: WOFF2 PRECONNECT SELF HOSTING SHARDING 😱
FONT-DISPLAY PRELOAD & FONT-SYNTHESIS CSS FONT LOADING API SUBSETTING VARIABLE FONTS
Slide 98
Slide 99
OUR OPPONENTS: INVISIBLE TEXT TEXT IN MOTION
Slide 100
RE F RE LO FLO W W RE F R L E RE FL OW FLO OW W
THE default Wordpress Site
first render 3.3s
visually complete
5.7s
Slide 101
PRELOAD EVERYTHING NO REFLOWS!
FIRST 😭 RENDER
🗑 New:
Baseline:
▲ 15% 3.8s first render 3.3s
▼
-1% 5.6s
visually complete 5.7s
Slide 102
R RE EFL FLO OW W RE FLO W
PRELOAD TWO FONTS ❤ FONT-SYNTHESIS
New:
3.3s
Baseline:
first render 3.3s
▼
-1% 5.6s
visually complete 5.7s
Slide 103
YYYYY CSS FONT LOADING API
Slide 104
LOAD A WEB FONT USING JS // Remove existing @font-face blocks // Make it let font = new FontFace( "Noto Serif", "url(notoserif.woff2) format('woff2')" ); // Load it let loadedFont = await font.load(); // Render it document.fonts.add(loadedFont); Full Code at https://github.com/zachleat/performance-sometime/blob/master/css-font-loading.js
Slide 105
LOAD TWO WEB FONTS USING JS
// Remove existing @font-face blocks // Make two let font = new FontFace("Noto Serif", /* … /); let fontBold = new FontFace("Noto Serif", / … */); // Load two let fonts = await Promise.all([ font.load(), fontBold.load() ]); // Render them at the same time!!! fonts.forEach(font => document.fonts.add(font));
Full Code at https://github.com/zachleat/performance-sometime/blob/master/css-font-loading.js
Slide 106
NO CSS MAINTENANCE REQUIRED 🎉
Slide 107
YYYYY
ON ER EF LO W
SELF HOSTING AND Font-DISPLAY AND PRELOAD: 2 of 5 AND SHARDING: 3 of 5 WITH PRECONNECT
AND CSS FONT LOADING: 3 of 5
New:
3.3s
5.7s
Baseline:
first render 3.3s
visually complete 5.7s
Slide 108
ROMAN
FALLBACK
FAUX-BOLD
FONT-SYNTHESIS
BOLD 🏁 @zachleat
Slide 109
ROMAN
FONT-SYNTHESIS
FAUX-BOLD
BOLD 🏁 @zachleat
❤
Slide 110
JavaScript FONTS CAN BE FANCY: NETWORK INFORMATION API Opt out of fonts on slow connections
https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API
Save-Data
Opt-out of fonts when the user has enabled Data Saver mode. https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/save-data/
PREFERS-REDUCED-MOTION
https://webkit.org/blog/7551/responsive-design-for-motion/#using-reduce-motion-on-the-web
@zachleat
Opt-out of font reflows when the user has enabled Reduce Motion in accessibility preferences.
Slide 111
OUR TOOLS: WOFF2 PRECONNECT SELF HOSTING SHARDING 😱
FONT-DISPLAY PRELOAD CSS FONT LOADING API SUBSETTING VARIABLE FONTS
Slide 112
Slide 113
Slide 114
https://www.axis-praxis.org/
https://www.preusstype.com
Slide 115
YYYY Y 15.3KB 15.4KB
22.9KB
20.9KB
26.4KB
100.9KB
Slide 116
Y Y
100.0KB
CompressaPRO-GX.woff2 Read more about Variable Font size comparisons: http://stuff.djr.com/gimlet-vf-size-test/
Slide 117
YYYYY
SELF HOSTING WITH A SINGLE 115KB VARIABLE FONT
BASE LINE ▼
👀
New:
Baseline:
first render 3.3s
visually complete 5.7s
Slide 118
YYYYY
SELF HOSTING WITH A SINGLE 115KB VARIABLE FONT
👀
New:
Baseline:
first render 3.3s
visually complete 5.7s
Slide 119
YYYYY
SELF HOSTING WITH A SINGLE 115KB VARIABLE FONT
W LO EF ER ON
New:
Baseline:
first render 3.3s
visually complete 5.7s
Slide 120
v-fonts.com
Region 1 ntitled 2 ntitled 5 ntitled 8 titled 11 titled 14 titled 17 titled 20 titled 23 0
75
150
225
69.3 KB mean 54.1 KB Median
300
Slide 121
OUR TOOLS: WOFF2 PRECONNECT SELF HOSTING SHARDING 😱
FONT-DISPLAY PRELOAD CSS FONT LOADING API SUBSETTING VARIABLE FONTS
Slide 122
YYYYY
SELF HOSTING AND Font-DISPLAY AND PRELOAD: 2 of 5 AND SHARDING: 3 of 5 WITH PRECONNECT
AND CSS FONT LOADING: 3 of 5
New:
3.3s
5.7s
Baseline:
first render 3.3s
visually complete 5.7s
Slide 123
OUR TOOLS: WOFF2 PRECONNECT SELF HOSTING SHARDING 😱
FONT-DISPLAY PRELOAD CSS FONT LOADING API SUBSETTING VARIABLE FONTS
Slide 124
OUR TOOLS: WOFF2 PRECONNECT SELF HOSTING SHARDING 😱
FONT-DISPLAY PRELOAD CSS FONT LOADING API SUBSETTING VARIABLE FONTS
Slide 125
OUR TOOLS: WOFF2 PRECONNECT SELF HOSTING SHARDING 😱
FONT-DISPLAY PRELOAD CSS FONT LOADING API SUBSETTING VARIABLE FONTS
Slide 126
OUR OPPONENTS: INVISIBLE TEXT TEXT IN MOTION
-ISH
Slide 127
All demos on GitHub
https://github.com/zachleat/performance-sometime
Slide 128
A COMPREHENSIVE GUIDE TO
FONT LOADING
STRATEGIES zachleat.com/web/comprehensive-webfonts/
@zachleat
45 (and counting) font loading blog posts at zachleat.com/web/fonts/ Web Font Loading Recipes
https://github.com/zachleat/web-font-loading-recipes
Slide 129
Slide 130
@zachleat
THANK YOU
@zachleat @zachleat.com
\