A presentation at performance.now() in November 2018 in Amsterdam, Netherlands by Zach Leatherman
@zachleat @zachleat @zachleat.com @Anvil transition enthusiast
WHYs THE 5 WHYs OF WEB WHYs LOADIN WHYs PERFOR WHYs
WHYs WHYs OF WEB FONT WHYs LOADING WHYs PERFORMANCE WHYs
@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
@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
Y THE 5Y OF WEB FONT Y LOADING Y PERFORMANCE Y
THE DEFAULT Wordpress Site
THE DEFAULT Wordpress Site 595 KB 35 requests
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
Y SANS SERIF 15.3 KB
YY SANS SERIF BOLD 15.3 KB
YYY SERIF 22.9 KB
YYYY 20.8 KB SERIF ITALIC
YYYY Y 26.2 KB SERIF BOLD
All demos on GitHub https://github.com/zachleat/performance-sometime
https://www.webpagetest.org/ METHODOLOGY 3G Network Speed HTTP/2 and HTTPS CHROME & WOFF2 ONLY FONT OPTIMIZATIONS @zachleat
THE default Wordpress Site SERIF SANS-SERIF BOLD SERIF BOLD SERIF ITALIC SANS-SERIF first render 3.3s visually complete 5.7s
OUR OPPONENTS: INVISIBLE TEXT TEXT IN MOTION
OUR OPPONENTS: INVISIBLE TEXT FOIT TEXT IN MOTION
@zachleat https://twitter.com/jmuspratt/status/561239961924403200
OUR OPPONENTS: INVISIBLE TEXT TEXT IN MOTION FOUT
CRITICAL REQUEST CHAINS DOMCONTENTLOADED FIRST CONTENTFUL PAINT FIRST PAINT PERFORMANCE METRICS FIRST RENDER VISUALLY COMPLETE SPEED INDEX ONLOAD TIME TO INTERACTIVE CPU IDLE
FIRST RENDER FIRST CONTENTFUL PAINT
FIRST MEANINGFUL PAINT Finally a metric that PROPERLY accounts for web fonts 🎉 MEASURE using LIGHTHOUSE
OPPONENTS: INVISIBLE TEXT TEXT IN MOTION NEW METRIC: ALL TEXT VISIBLE
THE default Wordpress Site ALL TEXT VISIBLE first render 3.3s 👀 4.9s visually complete 5.7s
OPPONENTS: INVISIBLE TEXT TEXT IN MOTION NEW METRIC: WEB FONT REFLOW COUNT * After first render
REFLOW COUNTER 0 @zachleat
REFLOW COUNTER 10 @zachleat
REFLOW COUNTER 21 @zachleat
REFLOW COUNTER 32 @zachleat
REFLOW COUNTER 43 @zachleat
REFLOW COUNTER 54 @zachleat
REFLOW COUNTER 65 @zachleat
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
OUR METRICS: ALL TEXT VISIBLE WEB FONT REFLOW COUNT
YYYYY
YYYYY “WEB-SAFE”/SYSTEM/INSTALLED FONTS
YYYYY System fonts System Fonts: Baseline: ▼ -6% 3.1s first render 3.3s ▼ -10% 5.1s visually complete 5.7s
YYYYY System fonts No network requests INSTANT RENDERING @zachleat
@zachleat THANK YOU @zachleat @zachleat.com
@zachleat
BEST VIEWED @zachleat IN CHROME
@zachleat https://github.com/alrra/browser-logos
THE default Wordpress Site first render 3.3s visually complete 5.7s
OUR TOOLS: WOFF2 PRECONNECT SELF HOSTING SHARDING 😱 FONT-DISPLAY PRELOAD CSS FONT LOADING API SUBSETTING VARIABLE FONTS
YYYYY PRECONNECT
PRECONNECT 🎉 WITHOUT CSS WITH FONTS @zachleat
Preconnect Browser SUPPORT https://caniuse.com/#feat=link-rel-preconnect
PRECONNECT: GREAT FOR CROSS-ORIGIN FONT REQUESTS @zachleat
YYYYY THIRD PARTY ▸ SELF HOSTING
YYYYY SELF HOSTING BASE LINE ▼ 👀 Self Hosting: Baseline: ▼ -6% 3.1s first render 3.3s ▼ -1% 5.6s visually complete 5.7s
WHAT HAPPENED? SUPER LONG TTFB’S NETWORK CONGESTION BAD HTTP/2 prioritiZATION @zachleat Read more: https://blog.cloudflare.com/http-2-prioritization-with-nginx/
@font-face { src: url(notosans.woff2) format('woff2'); } ▼ @font-face { src: url(https://performance-sometimeassets.netlify.com/notosans.woff2) format('woff2'); }
YYYYY SELF HOSTING SELF HOST ▼ 👀 Self Hosting: Baseline: ▼ -6% 3.1s first render 3.3s ▼ -1% 5.6s visually complete 5.7s
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
***DON’T DO THIS, PROBABLY SHARDING IS AN ANTI-PATTERN ON HTTP/2 @zachleat
“ ONE PERSON’S TRASH IS ANOTHER PERSON’S -PATTERN TREASURE” ” ANTI-PATTERN
WHY SELF HOST? @zachleat
WHY SELF HOST? HOLD YOUR HORSES ⭐⭐⭐⭐🐴 @zachleat
YYYYY FONT-DISPLAY
@font-face { font-display: swap; } Shows Fallback Font Immediately, RENDER WEB FONT WHENEVER @zachleat Learn more: https://font-display.glitch.me/
@font-face { font-display: optional; } RENDER WEB FONT ONLY IF CACHED @zachleat Learn more: https://font-display.glitch.me/
font-display Browser SUPPORT https://caniuse.com/#feat=css-font-rendering-controls
font-display: swap -ish @zachleat
WE NO LONGER NEED JavaScript to load a WEB FONT *WITH VISIBLE FALLBACK TEXT @zachleat
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
YYYYY PRELOAD
PRELOAD BROWSER SUPPORT https://caniuse.com/#feat=link-rel-preload
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
PRELOADING fonts FROM A DIFFERENT ORIGIN INCURS CONNECTION COSTS AT A BAD TIME ⚠ @zachleat
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
OVERUSE OF PRELOAD WILL COST YOU in FIRST RENDER TIME ⚠ @zachleat
FIRST RENDER PRELOAD PRELOAD @zachleat PRELOAD
PRELOAD SOME, NOT ALL. HOW TO CHOOSE? @zachleat
LET’S GET… SUBJECTIVE
PRIORIZATION STRATEGY: USER DISRUPTION METRICS @zachleat
Y USER DISRUPTION Y Y Y Y PRIORIZATION YYYYY Y Y Y @zachleat Y
What reflows are most likely to BE THE MOST DISRUPTIVE? @zachleat
METRICS PRIORIZATION: PRELOAD ONE OF EACH FAMILY @zachleat YY YYY
Y METRICS PRIORIZATION: PRELOAD ONE OF EACH FAMILY Y Y YY YYY Y @zachleat ❤
ROMAN FALLBACK FAUX-BOLD FONT-SYNTHESIS ❤ BOLD 🏁 @zachleat
FONT-SYNTHESIS FALLBACK Y @zachleat 🚫 Y
DEAR WEB BROWSERS, CAN YOU COPY WEBKIT Please? NON-WEBKIT IT’S ME, MARGARET ❤ FONT-SYNTHESIS
OUR TOOLS: WOFF2 PRECONNECT SELF HOSTING SHARDING 😱 FONT-DISPLAY PRELOAD & FONT-SYNTHESIS CSS FONT LOADING API SUBSETTING VARIABLE FONTS
MINI- REVIEW
PRELOAD EVERYTHING NO REFLOWS! FIRST 😭 RENDER 🗑 New: Baseline: ▲ 15% 3.8s first render 3.3s ▼ -1% 5.6s visually complete 5.7s
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
YYYYY CSS FONT LOADING API
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
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
NO CSS MAINTENANCE REQUIRED 🎉
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
ROMAN FALLBACK FAUX-BOLD FONT-SYNTHESIS BOLD 🏁 @zachleat
ROMAN FONT-SYNTHESIS FAUX-BOLD BOLD 🏁 @zachleat ❤
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.
YYYY Y VARIABLE FONTS
YY VARIABLE FONTS
https://www.axis-praxis.org/ https://www.preusstype.com
YYYY Y 15.3KB 15.4KB 22.9KB 20.9KB 26.4KB 100.9KB
Y Y 100.0KB CompressaPRO-GX.woff2 Read more about Variable Font size comparisons: http://stuff.djr.com/gimlet-vf-size-test/
YYYYY SELF HOSTING WITH A SINGLE 115KB VARIABLE FONT BASE LINE ▼ 👀 New: Baseline: first render 3.3s visually complete 5.7s
YYYYY SELF HOSTING WITH A SINGLE 115KB VARIABLE FONT 👀 New: Baseline: first render 3.3s visually complete 5.7s
YYYYY SELF HOSTING WITH A SINGLE 115KB VARIABLE FONT W LO EF ER ON New: Baseline: first render 3.3s visually complete 5.7s
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
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
OUR OPPONENTS: INVISIBLE TEXT TEXT IN MOTION -ISH
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
@zachleat INSPIRED BY
@zachleat THANK YOU @zachleat @zachleat.com \
View The Five Whys of Web Font Loading Performance on Notist.
Dismiss
The following resources were mentioned during the presentation or are useful additional information.