What if you could make your pages load 20% faster?
https://www.flickr.com/photos/chrisjohnbeckett/10446312055
preloading is the single biggest performance
improvement browsers have ever made
Steve Souders, April 2013
https://hacks.mozilla.org/2013/03/capturing-improving-performance-of-the-adaptive-web/comment-page-1/#comment-2060698
www.stevesouders.com/blog/2013/04/26/i/
most destructive “performance enhancement”!
I think there’s ever been
Matt Wilcox, creator of Adaptive Images, March 2013
Matt’s point is a bit more nuanced than this, read the full discussion:!
https://hacks.mozilla.org/2013/03/capturing-improving-performance-of-the-adaptive-web/comment-page-1/#comment-2060698
The explosion in device diversity?
http://opensignal.com/reports/2014/android-fragmentation/
… or maybe latency is our greatest enemy
https://www.flickr.com/photos/jjvaca/728072059
At best network packets travel at roughly 2/3 speed of light
https://www.flickr.com/photos/98640399@N08/9287370881
London to New York Round Trip Time = 56ms over fibre!
https://www.flickr.com/photos/https://www.flickr.com/photos/lwr/6979975029 dpapworth/482125035
(TCP Segments)
TCP and the Lower Bound of Web Performance
John Rauser
Might take more than one round trip
285kB
214kB
143kB
71kB
1 2 3 4 5 6 7 8 9 10 11
Round Trips
Size
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
GET /styles.css HTTP/1.1
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
GET /more-styles.css HTTP/1.1
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
GET /script.js HTTP/1.1
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
Must wait for:!
1. CSS download and OM construction!
2. JS download and execution
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
GET /another-script.js HTTP/1.1
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
Must wait for:!
<body>
1. JS download and execution
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
GET /image.jpg HTTP/1.1
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
example.html
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="styles.css" rel="stylesheet">
<link href="more-styles.css" rel="stylesheet">
<script src="script.js"></script>
<script src="another-script.js"></script>
<title>HTML Example</title>
</head>
<body>
<h1>Title</h1>
<p>Some introductory text and picture! <img src="image.jpg"/></p>
<p>Some more text and another picture! <img src="image-2.jpg"/></p>
</body>
</html>
GET /image-2.jpg HTTP/1.1
What does the waterfall look like?
scripts download in series
WebPagetest - IE7, Cable, Korea
What if we decouple resource discovery from DOM construction?
When DOM construction is blocked !
! e.g. waiting for script to download and execute!
!
Search rest of document for external resources!
! e.g. <link rel=“stylesheet”…>, <script src=…>, <img src=…>!
!
Download and cache discovered resources ready for DOM
construction
IE 7 (doesn’t have a preloader)
IE 11 (has a preloader)
scripts download in series
parallel download,
execution still in series
Script inserted resources aren’t discoverable
<script type="text/javascript">
function() {
Browser won’t discover
script until outer script
inserts it into DOM
var js = document.createElement('script');
js.async = true;
js.src = 'script.js';
var e = document.getElementsByTagName('script')[0];
e.parentNode.insertBefore(js, first);
})();
</script>
Non-blocking loading using async attribute
!
<script async src="script.js"></script>
Widely supported (82%) and discoverable by preloader
Limits to what preloader can discover
HTML
CSS
DOM
CSSOM
Render!
Tree
JavaScript Layout Paint
Limits to what preloader can discover
HTML
CSS
DOM
CSSOM
Render!
Tree
Fonts and background
images discovered when
render tree builds
JavaScript Layout Paint
Possible workarounds?
dataURIs (will make CSS larger)!
HTTP/2 or SPDY server push!
<link rel=“subresource… (Chrome only and effectively broken)
Download order != Document order
https://www.flickr.com/photos/add1sun/4993432274
Browsers can prioritise download order
Based on:!
! Resource type - CSS, JS, image etc.!
! Visibility!
! Element attributes e.g. <script async, defer!
! W3C Resource Priorities
W3C Resource Priorities - adds lazyload attribute
(also look at Ilya Grigorik’s proposal for Resource Hints)
Prioritisation sometimes has unexpected consequences
These JS resources are
at the foot of the body!
(perhaps they should merge them into
fewer resources but…)
Watch out for the parser restarting
Content-Type: text/html
!
charset isn’t specified in HTTP
response so IE9 assumes ISO 8859-1
!
As it parses the HTML it then finds
!
<meta charset=“utf-8">
!
Similar issues can occur with <base>
Do odd things and you may get odd behaviour!
<html>
<head>
<script>
var file = window.innerWidth < 1000 ? "mobile.css" : "desktop.css";
document.write('<link rel="stylesheet" type="text/css" href="css/' + file + '"/>');
</script>
</head>
<body>
<img src="img/gallery-img1.jpg" />
<img src="img/gallery-img2.jpg" />
<img src="img/gallery-img3.jpg" />
<img src="img/gallery-img4.jpg" />
<img src="img/gallery-img5.jpg" />
<img src="img/gallery-img6.jpg" />
</body>
</html> This is based on a suggested Stack Overflow answer!
Do odd things and you may get odd behaviour!
IE 9 Download of CSS
blocked by images
Can use Cuzillion to test simple scenarios
https://www.stevesouders.com/cuzillion/
Latency is web performance enemy #1!
Preloader helps hide the latency!
Can only ‘see’ resources in markup!
May not load resources in order we intend!
Getting methods to hint our intent to browsers