My talk on web performance optimizations (including critical rendering path, better measurements, paint timings, custom font optimization, chrome performance observer and much more) from SMX West 2018 in San Jose.
3. #SMX #32A @basgr from @peakaceag
For me, there is nothing worse than having to wait for anything to load!
I’m not a very patient guy…
4. #SMX #32A @basgr from @peakaceag
Fast loading time plays an important role in overall user experience!
Performance = User experience!
5. #SMX #32A @basgr from @peakaceag
Revisited: PageSpeed (load time) is a ranking factor
Source: http://pa.ag/2iAmA4Y & http://pa.ag/2ERTPYY
6. #SMX #32A @basgr from @peakaceag
Google is obsessed site speed and keeps pushing for
faster sites all the time!
7. #SMX #32A @basgr from @peakaceag
Cognitive load with stressful situations
Source: Ericsson ConsumerLab, Neurons Inc. 2015
Solving a math problem
Experiencing mobile delays
Watching a horror movie
Standing at the edge of a virtual cliff
Watching a melodramatic TV show
Waiting in line at a retail store
Level of stress caused by
delays on mobile is
comparable to watching
a horror movie!
8. #SMX #32A @basgr from @peakaceag
Let’s get this straight – this is what your users expect:
Obviously, slow page loading time is a major factor in page abandonment.
According to a Nielsen report, 47% of people expect a
website to load within two seconds, and 40% will leave a
website if it does not load fully within three seconds.”
9. #SMX #32A @basgr from @peakaceag
Because the PageSpeed Insights score is not enough!
#1 Better measurement
10. #SMX #32A @basgr from @peakaceag
Translating experiences to performance metrics:
User experience
▪ Is it happening?
› Did the navigation start successfully?
Has the server responded?
▪ Is it useful?
› Has enough content rendered for users
to engage with it?
▪ Is it usable?
› Can users interact with the page or is it
still busy loading?
▪ Is it smooth/delightful?
› Are the interactions smooth and
natural, free of lag and jank?
Corresponding metric
First Paint (FP) / First Contentful Paint (FCP)
First Meaningful Paint (FMP) -> Hero Element Timing
Time to Interactive (TTI)
Long tasks (technically the absence of those long tasks)
11. #SMX #32A @basgr from @peakaceag
Optimizing and measuring for painting timings
#1 #2
First Paint (FP)
Time to First Paint – marks the point when the
browser starts to render something, the first bit of
content on the screen.
12. #SMX #32A @basgr from @peakaceag
Optimizing and measuring for painting timings
#1 #2 #3 #4
First Paint (FP) First Contentful
Paint (FCP)
Time to First Paint – marks the point when the
browser starts to render something, the first bit of
content on the screen.
Time to First Contentful Paint – marks the point when
the browser renders the first bit of content from the
DOM, text, an image etc.
13. #SMX #32A @basgr from @peakaceag
Optimizing and measuring for painting timings
#1 #2 #3 #4 #5 #6
First Paint (FP) First Contentful
Paint (FCP)
First Meaningful
Paint (FMP) / Hero!
Time to Interactive
(TTI)
Time to First Paint – marks the point when the
browser starts to render something, the first bit of
content on the screen.
Time to First Contentful Paint – marks the point when
the browser renders the first bit of content from the
DOM, text, an image etc.
14. #SMX #32A @basgr from @peakaceag
Care about your Hero (Element)!
Optimize for First Meaningful Paint
15. #SMX #32A @basgr from @peakaceag
Track paint timings with Google Analytics (in theory)
Get the tracking code snippets: http://pa.ag/2viHQSz
version 62 and up
You must ensure your
PerformanceObserver is
registered in the <head>
before any stylesheets, so it
runs before FP/FCP happens.
(a buffered flag TBD in v.2)
16. #SMX #32A @basgr from @peakaceag
This is how it looks like in Google Analytics
Behavior > events > pages: performance metrics [first-contentful-paint]
Source: Google Analytics
17. #SMX #32A @basgr from @peakaceag
The cool kids’ way of doing this (using GTM):
#1 #3
#2 #4
18. #SMX #32A @basgr from @peakaceag
Combine it with Google Data Studio:
Test it: http://pa.ag/2Ee550q
19. #SMX #32A @basgr from @peakaceag
The code and resources required to render the initial view of a web page
#2 Critical rendering path
20. #SMX #32A @basgr from @peakaceag
Critical rendering path optimization
Initial view
(critical)
Below the fold
(not critical)
21. #SMX #32A @basgr from @peakaceag
CSSOM: the CSS Object Model
▪ The CSSOM is a “map” of the CSS styles
found on a web page.
▪ It’s much like the DOM (Document Object
Model), but for CSS rather than HTML.
▪ The CSSOM combined with the DOM is
used by browsers to display web pages.
body
font-size:16px;
h1
font-size:22px;
p
font-size:16px;
p
font-size:12px;
a
font-size:12px;
img
font-size:16px;
22. #SMX #32A @basgr from @peakaceag
Web browsers use the CSSOM to render a page
23. #SMX #32A @basgr from @peakaceag
Google doesn’t make a single GET request for its CSS!
24. #SMX #32A @basgr from @peakaceag
How to know which CSS is critically required?
▪ Minimum: a snapshot of CSS rules to
render a default desktop resolution (e.g.
1280x1024).
▪ Better: various snapshots for mobile
phones, pad/s & desktop/s – a lot of work!
Source: http://pa.ag/2o4x0uE
25. #SMX #32A @basgr from @peakaceag
My favorite: “critical” (using Node / Phantom JS)
Renders a site in multiple resolutions & builds a combined and compressed CRP CSS:
Critical & criticalCSS on GitHub: http://pa.ag/2wJTZAu & http://pa.ag/2wT1ST9
26. #SMX #32A @basgr from @peakaceag
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>CRP loading demo</title>
<!-- critical CSS goes here -->
<style> h1 { color: green; } </style>
<!-- use async preload // no IE, Edge & some other unimportant ones (http://caniuse.com/#search=preload) -->
<link rel="preload" href="non-critical.css" as="style" onload="this.rel='stylesheet'" />
<!--noscript for req. without JS -->
<noscript><link rel="stylesheet" href="non-critical.css"></noscript>
<!-- include polyfill for shitty browsers -->
<script>
*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
(function(){ ... } ());
/*! loadCSS rel=preload polyfill. [c] 2017 Filament Group, Inc. MIT License */
(function(){ ... } ());
</script>
</head>
<body>
</body>
</html>
<!-- use async preload // no IE, Edge & some other unimportant ones
(http://caniuse.com/#search=preload) -->
<link rel="preload" href="non-critical.css" as="style" onload="this.rel='stylesheet'" />
<!-- critical CSS goes here -->
<style> h1 { color: green; } </style>
<!-- use async preload // no IE, Edge & some other unimportant ones
(http://caniuse.com/#search=preload) -->
<link rel="preload" href="non-critical.css" as="style" onload="this.rel='stylesheet'" />
<!--noscript for req. without JS -->
<noscript><link rel="stylesheet" href="non-critical.css"></noscript>
*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
(function(){ ... } ());
/*! loadCSS rel=preload polyfill. [c] 2017 Filament Group, Inc. MIT License */
(function(){ ... } ());
Putting it all together
Fit the HTML, CSS & JS that’s necessary for “Start Render” into that first 14 kB round trip!
Inline your critical CSS
1
Loading non-critical CSS
async using rel=“preload“
2
Apply the CSS once it has
finished loading via “onload“
3
Fallback for non-JS requests
4
Implement loadCSS script for
older browsers
5
27. #SMX #32A @basgr from @peakaceag
Let’s look at an actual implementation…
Is it worth the effort?
28. #SMX #32A @basgr from @peakaceag
Before & after: a fresh WordPress setup #1
HTTP, no HTTP/2, Twenty Seventeen theme (1x CSS, 8x JS, custom fonts), no caching
and no other performance optimizations
29. #SMX #32A @basgr from @peakaceag
Before & after: a fresh WordPress setup #2
HTTP, no HTTP/2, Twenty Seventeen theme (1x CSS, 8x JS, custom fonts), W3Total (CSS,
JS, HTML minify, caching, compression)
30. #SMX #32A @basgr from @peakaceag
Before & after: a fresh WordPress setup #3
HTTP, no HTTP/2, Twenty Seventeen theme (1x CSS, 8x JS, custom fonts), W3Total (CSS,
JS, HTML minify, caching, compression) + CRP CSS inlined
31. #SMX #32A @basgr from @peakaceag
Performance metrics comparison at a glance
Rendering starts significantly earlier; this allows for faster interaction with the site.
KPI / MEASUREMENT
Load Time
Time to First Byte (TTFB)
Start Render
Time to Interactive (TTI)
DEFAULT WP
1.357 sec
0.454 sec
1.000 sec
0.956 sec
BASIC PERFORMANCE
0.791 sec
0.159 sec
0.600 sec
0.931 sec
FULLY OPTIMIZED
0.789 sec
0.157 sec
0.410 sec
0.563 sec
(+32%)
(+41%)
32. #SMX #32A @basgr from @peakaceag
Implement proper tracking, measure “First Meaningful Paint” (Hero Element delivery).
Audit, clean and (afterwards) split CSS into two parts: “initial view” and “below the fold”.
Use “critical” to generate and inline your critical path CSS.
Use rel=“preload“ and “loadCSS” to async load below the fold / site-wide CSS.
Off-load all overhead (JS, etc.) to stay within 14kB for faster, initial paint.
#SMXInsights
Share these #SMXInsights on your social channels!
33. #SMX #32A @basgr from @peakaceag
Pretty, varied, colorful, and slow!
#3 Custom web fonts
34. #SMX #32A @basgr from @peakaceag
68% of all websites use at least one non-standard font!
Result: 114 kB additional data and on average 2.9 HTTP requests
Source: http://pa.ag/1BRUnbe
Font transfer size & font requests Sites with custom fonts
Font transfer size (kB) Font requests
35. #SMX #32A @basgr from @peakaceag
Classic scenario: using external CSS
Easy to use with one big disadvantage: CSS is render-blocking!
36. #SMX #32A @basgr from @peakaceag
Load custom fonts with FontLoader
Google's asynchronous solution: webfont.js (JavaScript loads first, then CSS)
37. #SMX #32A @basgr from @peakaceag
Not very successful and also problematic
FOUT (flash of unstyled text) = super annoying flickering
Fighting the FOUT: http://pa.ag/1BRWMmu
38. #SMX #32A @basgr from @peakaceag
How I usually tackle this
Credits: http://pa.ag/1GakitY & http://pa.ag/1NDXCVi
39. #SMX #32A @basgr from @peakaceag
New stuff to play around with: “font-display” strategies
More: http://pa.ag/2eUwVob
40. #SMX #32A @basgr from @peakaceag
Highest quality, (more) efficient data compression, smaller files
It hasn’t fully caught on yet, but it is very exciting!
#4 New image formats
41. #SMX #32A @basgr from @peakaceag
62% of all web traffic is made up of images...
… and 51% of all URLs load more than 40 images per request.
Source: http://pa.ag/1SGDOEo
Average bytes per page by content type Image requests per page
42. #SMX #32A @basgr from @peakaceag
WebP: Google’s alternative to JPEG, PNG, and GIF
Lossy and lossless compression, transparency, metadata, color profiles, animation, and
much smaller files (30% vs. JPEG, 80% vs. PNG)
Everything about WebP: http://pa.ag/1EpFWeN
43. #SMX #32A @basgr from @peakaceag
We’re not quite there yet...
Currently only supported by Chrome, Opera, and Android
Source: http://pa.ag/2FZK4XS
44. #SMX #32A @basgr from @peakaceag
You can still use WebP with on-the-fly replacement
Swap PNG and JPEG images per re-write (i.e., using .htaccess)
45. #SMX #32A @basgr from @peakaceag
You can still use WebP with on-the-fly replacement
Swap PNG and JPEG images per re-write (i.e., using .htaccess)
VS.
46. #SMX #32A @basgr from @peakaceag
Using HTML5 and <picture> with newer templates
Browsers, which don‘t support <picture> will ignore this. <source> browsers, which
don't support WebP, will use <img> as a fallback.
47. #SMX #32A @basgr from @peakaceag
There is more: FLIF, BPG etc.
Left: image size compared to original PNG
Further reading: http://pa.ag/1S5OQmX
48. #SMX #32A @basgr from @peakaceag
It really depends on the visual itself:
49. #SMX #32A @basgr from @peakaceag
Talking about image file types…
50. #SMX #32A @basgr from @peakaceag
Guetzli: 35% smaller JPEGs due to better encoding
No new file type needed at all; operating systems and browsers don’t need to adapt!
Source: http://pa.ag/2nyZjxf
52. @peakaceag with @basgr#SMX #32A
Make sure to get the basics right!
▪ Optimize images: reduce overhead for JPGs & PNGs (metadata,
etc.), request proper sized images and try new formats.
▪ Implement effective caching and compression.
▪ Whenever possible, use asynchronous requests.
▪ Decrease size of CSS and JavaScript files (minify).
▪ Use a content distribution network (CDN) / an asset server
(as well as cookie-less domains) to optimize parallel requests.
▪ Lean mark-up (no comments, use inline CSS / JS only where
necessary or useful)
▪ Consider (DNS) pre-fetching & pre-rendering if feasible.
▪ Watch (& optimize) for TTFB, don’t forget you back-end
architecture / systems (e.g. DB, webserver etc.).
All slides on SlideShare: http://pa.ag/iss17speed
Use my checklist on SlideShare to double check:
53. #SMX #32A @basgr from @peakaceag
http://pa.ag/smxw18spd
Always looking for talent! Check out jobs.pa.ag
Bastian Grimm
bg@pa.ag
twitter.com/peakaceag
facebook.com/peakaceag
www.pa.ag
Liked the deck? Here you go: