Upload
andy-davies
View
5.730
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Slides from talk at London Webstandards (Sept 2014) on what the browser preloader is, how it works and why we need it
Citation preview
https://www.flickr.com/photos/benjreay/14713228051
What does the browser pre-loader do?
@andydavies Sept 2014
The Preloader!
A.K.A.!
look-ahead or speculative pre-parser
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-2060698www.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
What’s our greatest enemy?
https://www.flickr.com/photos/54459164@N00/5218183788
The browser that just won’t die?
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/dpapworth/482125035https://www.flickr.com/photos/lwr/6979975029
TCP and the Lower Bound of Web Performance John Rauser
Might take more than one round trip
71kB
143kB
214kB
285kB
1 2 3 4 5 6 7 8 9 10 11
(TCP Segments)
Round Trips
Size
So what’s this got to do with the preloader?
Let’s pretend we’re a browser (with the preloader switched off)
https://www.flickr.com/photos/mozillaeu/11171168996
Two key rules to remember
Constructing CSS Object Model (CSSOM) blocks JavaScript execution!!
JavaScript blocks DOM construction
GET example.html HTTP/1.1
GET example.html HTTP/1.1
<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"> <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
GET /styles.css HTTP/1.1
<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
GET /more-styles.css HTTP/1.1
<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
GET /script.js HTTP/1.1
<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
Must wait for:!1. CSS download and OM construction!2. JS download and execution
<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
GET /another-script.js HTTP/1.1
<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
Must wait for:!1. JS download and execution
<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
GET /image.jpg HTTP/1.1
<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
GET /image-2.jpg HTTP/1.1
What does the waterfall look like?
WebPagetest - IE7, Cable, Korea
scripts download in series
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
link rel=“stylesheet” ✓ ✓ ✓ ✓ ✓<script src= ✓ ✓ ✓ ✓ ✓<img> ✓ ✓ ✓ ✓ ✓@import ✓ ✓ ✓<video poster> ✓<picture> <img> ✓ ✓
What gets preloaded?
http://yoavweiss.github.io/preloader-velocity-nyc-talk
Script inserted resources aren’t discoverable
<script type="text/javascript"> function() { var js = document.createElement('script'); js.async = true; js.src = 'script.js'; var e = document.getElementsByTagName('script')[0]; e.parentNode.insertBefore(js, first); })(); </script>
Browser won’t discover script until outer script inserts it into DOM
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 Layout PaintJavaScript
Limits to what preloader can discover
HTML
CSS
DOM
CSSOM
Render!Tree Layout PaintJavaScript
Fonts and background images discovered when render tree builds
Possible workarounds?
dataURIs (will make CSS larger)!
HTTP/2 or SPDY server push!
<link rel=“subresource… (Chrome only and effectively broken)
Download order != Document orderhttps://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
Major UK retailer’s site in Chrome
Prioritisation sometimes has unexpected consequences
These JS resources are at the foot of the body!(perhaps they should merge them into fewer resources but…)
Prioritisation sometimes has unexpected consequences
Downloading the JS blocks the hero image
Some edge cases you might come across
Watch out for the parser restarting
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 9Download 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
https://www.flickr.com/photos/auntiep/5024494612
!
@andydavies!!
http://slideshare.net/andydavies!