Simon Hearne
Web Performance Consultant
The BBC loses an additional 10% of users for every additional second it takes to load | |
Pinterest improved load time by 40% and saw 15% increase in SEO traffic and 15% increase in conversions | |
Financial Times added a one second delay to every page view and saw a 4.9% drop in the number of articles users read over a 7 day window | |
For every 100ms decrease in homepage load speed, Mobify's customer base saw a 1.11% lift in session based conversion |
Speed is now a landing page factor for Google Search and Ads
SEO
Product
Marketing
Operations
Development
User Experience
Business Intelligence
But who owns it?
In Chrome Developer Tools / Audits
Identify large & slow resources
Identify rendering & JavaScript bottlenecks
developers.google.com/web/tools/chrome-devtools/remote-debugging/
Analyse resources over the network.
Compare visual output to the network waterfall.
Test internal environments, bulk tests, API key management.
Regular tests on fixed pages / journeys, using browsers hosted on servers.
Good for testing availability and infrastructure performance.
* other services are available
Collect performance data from every visitor
* other services are available
* other services are available
Provide data for synthetic & real user monitoring
* only total duration for crossorigin requests without timing-allow-origin response header
* <link rel="dns-prefetch" href="//thirdparty.com"/>
Reducing tound-trip latency *
* optimising RTT benefits all stages
Approximately 50% faster than TLS 1.2!
Finding the maximum safe bandwidth on a connection
*HTTP/2 only has one connection per domain, packet loss has a greater impact than HTTP/1.x
Fraida Fund | TCP congestion control in lossy wireless networks
Ensure that your HTML document (including response headers) fits comfortably into your initial congestion window (initcwnd * 1400B
)
Rewriting the network layer
<link rel="dns-prefetch|preconnect|prefetch|preload" href="...">
dns-prefetch
- resolve hostname as soon as possiblepreconnect
- establish TCP & TLS connectionprefetch
- download this when you're readypreload
- download this as soon as possible!* use with caution - too many can break browser prioritisation and make a page slower!
Tell the browser what is important
<link rel="dns-prefetch|preconnect|prefetch|preload" href="...">
Available in Chrome 74 as origin trial, general availability in Chrome 76
Free up the network for critical resources
<img loading="auto|eager|lazy" src="...">
<iframe loading="auto|eager|lazy" src="..."></iframe>
Desktop Image Bytes are up 330% since 2011
Mobile Image Bytes are up 1050% since 2011
Bitmap (PNG / JPG)
Grid of pixels, does not scale well
Vector (SVG)
Shapes defined in XML, scales infinitely!
150px
20kB
300px
27kB
450px
86kB
150px
18kB
300px
18kB
450px
18kB
Photo Imagery
JPG
(lossy compression)
Icons & Graphics
SVG / PNG(lossless compression)
Animations
GIF / CSS(lossless compression)
Chrome & Opera
Safari
Internet Explorer
Responsive web design gives us an image problem.
srcset
Send the right DPR image, e.g. 1x to desktop & 2x to retina
<img src="src.png" srcset="1x.png 1x, 2x.png 2x, 3x.png 3x, 4x.png 4x">
srcset
You probably don't need > 2x?
srcset
Send an image scaled to the viewport
<img src="medium.jpg" srcset="medium.jpg 500w, large.jpg 1000w, extralarge.jpg">
srcset
Is the viewport relevant to image size?
srcset
Including responsive breakpoints
<img src="medium.jpg" srcset="medium.jpg 800w, large.jpg" sizes="(max-width: 800px) 100vw, 33vw">
<picture>
Art direction for different displays
<picture>
<source srcset="wide.png" media="(min-width: 800px)">
<img src="slim.png" srcset="slim.png">
</picture>
<picture>
& srcset
It gets complicated...
<picture>
<source srcset="xsmall.jpg 1x, xsmall@2x.jpg 2x" media="(max-width: 37.4375em)">
<source srcset="small.jpg 1x, small@2x.jpg 2x" media="(min-width: 37.5em) and (max-width: 64.4375em)">
<source srcset="medium.jpg 1x, medium@2x.jpg 2x" media="(min-width: 64.5em) and (max-width: 79.9375em)">
<source srcset="large.jpg 1x, large@2x.jpg 2x" media="(min-width: 80em) and (max-width: 119.9375em)">
<source srcset="xlarge.jpg 1x, xlarge@2x.jpg 2x" media="(min-width: 120em)">
<img src="medium.jpg">
</picture>
Perform content selection on the server / CDN
developers.google.com | Automating Content Selection with Client Hints
<img loading="auto|eager|lazy" src="...">
Allows the browser to determine which images to download immediately, based on viewport and connection speed.
Available in Chrome 76, polyfill with lazysizes.js
You’re building your own maze, in a way,
and you might just get lost in it.
Marijn Haverbeke, Eloquent JavaScript: A Modern Introduction to Programming
Desktop JavaScript is up 350% since 2011
Mobile JavaScript is up 650% since 2011
Use for immutable, versioned assets. Best possible caching!
cache-control: immutable, max-age=31536000
Use for assets which may change. Validation uses an extra round-trip.
cache-control: max-age:86400
ETag: "33a64...f89d4"
Use for assets which may change. Validation uses an extra round-trip.
cache-control: max-age:86400
Last-Modified:
Use for frequently updated assets (feeds, product lists)
cache-control: no-cache
ETag: "33a64...f89d4"
Use for sensitive responses (set-cookie, user-specific)
cache-control: no-store
<script src="//code.jquery.com/jquery-1.7.1.min.js"></script>
Single Point of Failure blank screen duration:
Windows: 30s | Android: 60s | MacOS: 75s | iOS: 75s
Main thread blocked for over six seconds by Campaign Monitor
1.6s delay on click event, caused by third-party scripts
Validate resources against a crypto hash.
Protects against malicious code changes, not poor performance!
<script
src="//thirdparty.com/script.js"
integrity="sha256-ivk71nXhz9nsyFDoYoGf2...=">
</script>
Only allow scripts / images / frames from pre-approved domains
Content-Security-Policy:
default-src 'self';
img-src *;
media-src media1.com media2.com;
script-src userscripts.example.com
Validate resources against a crypto hash.
Protects against malicious code changes, not poor performance!
Report-To:
{
"group": "csp-endpoint",
"max_age": 10886400,
"endpoints": [{
"url": "https://example.com/csp-reports"
}]
},{
"group": "network-endpoint",
"max_age": 10886400,
"endpoints": [{
"url": "https://example.com/network-errors"
}]
},{
"max_age": 10886400,
"endpoints": [{
"url": "https://example.com/browser-errors"
}]
}
Serve third party content from your domain
Time out slow responses
function timeout(delay) {
return new Promise(function(resolve, reject) {
setTimeout(function(){
resolve(new Response('', {
status: 408,
statusText: 'Request timed out.'
}));
}, delay);
});
}
self.addEventListener('fetch', function(event) {
if (/\.js$/.test(event.request.url)) {
event.respondWith(Promise.race([timeout(2000), fetch(event.request.url)]));
} else {
event.respondWith(fetch(event.request));
}
});
Akamai | 5 ways to prevent slow 3rd party front-end services
simon@hearne.me