progressive downloads and rendering

126
Progressive downloads and rendering Stoyan Stefanov, Yahoo! HighLoad++, Moscow, 2010 http://slideshare.net/stoyan/

Upload: luana

Post on 14-Feb-2016

23 views

Category:

Documents


0 download

DESCRIPTION

Progressive downloads and rendering. Stoyan Stefanov, Yahoo! HighLoad ++, Moscow, 2010 http://slideshare.net/stoyan/. About me. YSlow 2.0. Why progressive?. Importance of performance. Psychology, physiology Effects of waiting “Time is money” Make people happy. Perception. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Progressive downloads  and rendering

Progressive downloads

and rendering

Stoyan Stefanov, Yahoo! HighLoad++, Moscow, 2010http://slideshare.net/stoyan/

Page 2: Progressive downloads  and rendering

About meYSlow 2.0

Page 3: Progressive downloads  and rendering

Why progressive?

Page 4: Progressive downloads  and rendering

Importance of performance• Psychology, physiology • Effects of waiting• “Time is money”• Make people happy

Page 5: Progressive downloads  and rendering

Perception

Page 6: Progressive downloads  and rendering

Perception

Page 7: Progressive downloads  and rendering

Perception

Page 8: Progressive downloads  and rendering

Perception

Page 9: Progressive downloads  and rendering
Page 10: Progressive downloads  and rendering
Page 11: Progressive downloads  and rendering

Time is relative• Sometimes crawls• Sometimes flies• “it depends”

Page 12: Progressive downloads  and rendering

Durations

actual

expectedperceived

rem’d

time

Page 13: Progressive downloads  and rendering

It feels slower when…• Unpleasant• Unknown• Boring• Too much to keep track

Page 14: Progressive downloads  and rendering

First time experience• Unfamiliar = slow• Optimize empty cache or

there will be no full cache

Page 15: Progressive downloads  and rendering

So… go progressive!

Page 16: Progressive downloads  and rendering

But before we begin…

Page 17: Progressive downloads  and rendering

The basics• Reducing the # HTTP• Gzip• Minification• Image smushing• Expires• CDN

Page 18: Progressive downloads  and rendering

The basics• Yahoo!’s best practices +

YSlowhttp://developer.yahoo.com/performance/

• Google’s too + Page Speed

http://code.google.com/speed/

Page 19: Progressive downloads  and rendering

Progressive

Page 20: Progressive downloads  and rendering

Progressive enhancement

Page 21: Progressive downloads  and rendering

Progressive downloads

Page 22: Progressive downloads  and rendering
Page 23: Progressive downloads  and rendering

Progressive rendering

Page 24: Progressive downloads  and rendering

Agenda1. Prevent download blocks:

scripts, styles, CC, favicon2. Ways to render sooner:

flush, data URIs, lazy loading, lazy evaluation, preloading, animations

Page 25: Progressive downloads  and rendering

Blocking JavaScript

Page 26: Progressive downloads  and rendering

JavaScript blocks

htmljs

pngpng

Page 27: Progressive downloads  and rendering

JavaScript blocks• A no-no!

<script src="jquery.js"></script><script src="jquery.twitter.js"></script><script src="jquery.cookie.js"></script><script src="myapp.js"></script>

Page 28: Progressive downloads  and rendering

This waterfall looks ridiculous

htmljs

pngpng

jsjs

js

Page 29: Progressive downloads  and rendering

JavaScript at the bottom

html

js

pngpng

Page 30: Progressive downloads  and rendering

Non-blocking JavaScript• defer and async• Defer: IE innovation, ok to

delay, but keep order• Async: HTML5, whatever<script async src="my.js"

onload="doIt()"></script><script defer src="my.js"

onload="doIt()"></script>

Page 31: Progressive downloads  and rendering

defer and async timeline

DOMContentLoaded load

async

defer

Page 32: Progressive downloads  and rendering

Non-blocking JavaScript• Asynchronous loading

var h, js = document.createElement('script');js.src = 'myscript.js';h = document.getElementsByTagName('head')[0];h.appendChild(js);

htmljs

pngpng

Page 33: Progressive downloads  and rendering

Non-blocking JavaScript• Others:

- iframe- XHR- <object>- …

Page 34: Progressive downloads  and rendering

CSS and rendering

Page 35: Progressive downloads  and rendering

Worst enemy?

CSS

Page 36: Progressive downloads  and rendering

CSS blocks rendering• The worst component type• Place way at the top• @media print, etc in the same external CSS

http://www.phpied.com/delay-loading-your-print-css/http://www.phpied.com/rendering-styles/

Page 37: Progressive downloads  and rendering

CSS

Page 38: Progressive downloads  and rendering

CSS

Page 39: Progressive downloads  and rendering

CSS blockdownloads?

But they do block:• When followed

by an inline script• When in conditional

comments

Page 40: Progressive downloads  and rendering

Inline CSS• Google search• Bing.com: inline + postload

Page 41: Progressive downloads  and rendering

Same domain• If you split across domains• and if you don’t use CDN• Saves a DNS lookup

• e.g. Google and Bing’s CDN

Page 42: Progressive downloads  and rendering

CC block

Page 43: Progressive downloads  and rendering

Normal page

Page 44: Progressive downloads  and rendering

With conditionally commented CSS file

http://www.phpied.com/conditional-comments-block-downloads/

Page 45: Progressive downloads  and rendering

What…?! Case #1 <link type="text/css" rel="stylesheet" href="1.css"> <!--[if IE 6]> <link type="text/css" rel="stylesheet" href="ie.css"> <![endif]-->

Page 46: Progressive downloads  and rendering

What…?! Case #2<!--[if IE 6]> <body class="ie6"> <![endif]--><!--[if !IE]><!--> <body><!--<![endif]-->

Page 47: Progressive downloads  and rendering

Solution for case #1<!DOCTYPE html><!--[if IE 6]><![endif]-->

<html> ...

Page 48: Progressive downloads  and rendering

Solution for case #2<!--[if IE 6]> <html class="ie6"> <![endif]--><!--[if !IE]><!--> <html><!--<![endif]-->

Page 49: Progressive downloads  and rendering

Blocking favicon

Page 50: Progressive downloads  and rendering
Page 51: Progressive downloads  and rendering

Flush

Page 52: Progressive downloads  and rendering

flush() earlyhtml

pngjs

css

html

pngjs

css

Page 53: Progressive downloads  and rendering

flush()<html><head> <script src="my.js"

type="text/javascript"></script> <link href="my.css"

type="text/css" rel="stylesheet" /></head>

<body> ....

<?php flush() ?>

Page 54: Progressive downloads  and rendering

Chunked encodingHTTP/1.1 200 OKContent-Type: text/plainTransfer-Encoding: chunked

25This is the data in the first chunk

1Cand this is the second one

0

Page 55: Progressive downloads  and rendering

Chunked encoding

• Progressive rendering- Semantic app chunksvs.- Server-level chunks

Page 56: Progressive downloads  and rendering

Progressive renderingChunk #1

Chunk #2

Chunk #3

Page 57: Progressive downloads  and rendering

<!doctype html><html><head><title>My App</title></head><body> <div id="header"> <img src="logo.png" /> ... </div> <!-- end of chunk #1 --> ... The full body of the page ... <!-- end of chunk #2 -->

<script src="all_20100925.js"></script></body></html> <!-- end of chunk #3 -->

Page 58: Progressive downloads  and rendering

Progressive + source order

1

23

4

Page 59: Progressive downloads  and rendering

HTTP chunking: not only HTML

Page 60: Progressive downloads  and rendering

HTTP chunking: not only HTML• Google Instant• /*""*/ - delimited JSON

pieces• Chunk #1 suggestions• Chunk #2 results

http://tinyurl.com/chunkview

Page 61: Progressive downloads  and rendering

Data URIs

Page 62: Progressive downloads  and rendering

Fewer HTTP requests• Inline images:

in CSS spriteswith data: URI scheme

http://csssprites.com http://spriteme.org

Page 63: Progressive downloads  and rendering

Fewer HTTP requests• data: URI scheme

$ php -r "echo base64_encode(file_get_contents('my.png'));”iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAGElEQVQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC

Page 64: Progressive downloads  and rendering

Fewer HTTP requests• data: URI scheme

background-image: url("data:image/png;base64,iVBORw0KG...");

Page 65: Progressive downloads  and rendering

Fewer HTTP requests• data: URI scheme

<img src="data:image/png;base64,iVBOR..." />

Page 66: Progressive downloads  and rendering
Page 67: Progressive downloads  and rendering
Page 68: Progressive downloads  and rendering

Both• flushes• data: URIs

Page 69: Progressive downloads  and rendering
Page 70: Progressive downloads  and rendering
Page 71: Progressive downloads  and rendering

Fewer HTTP requests• data: URI scheme• works in IE!...

Page 72: Progressive downloads  and rendering

Fewer HTTP requests• data: URI scheme• works in IE8!

Page 73: Progressive downloads  and rendering

Fewer HTTP requests• data: URI scheme• MHTML for IE < 8

Page 74: Progressive downloads  and rendering
Page 75: Progressive downloads  and rendering
Page 76: Progressive downloads  and rendering
Page 77: Progressive downloads  and rendering
Page 78: Progressive downloads  and rendering
Page 79: Progressive downloads  and rendering
Page 80: Progressive downloads  and rendering
Page 81: Progressive downloads  and rendering

MHTML • MIME HTML• Works in IE 6,7• Indeed it actually absolutely does work in IE7/Vista too

http://phpied.com/the-proper-mhtml-syntax/

Page 82: Progressive downloads  and rendering

MHTML - one partContent-Location: myimageContent-Transfer-Encoding: base64

iVBORw0KGgoAAAANSU....U5ErkJggg==

Page 83: Progressive downloads  and rendering

MHTML - multi partsContent-Type: multipart/related; boundary="MYSEPARATOR"

--MYSEPARATOR

[here comes part one]

--MYSEPARATOR

[here's part two]

--MYSEPARATOR--

The double-dash of doom

Page 84: Progressive downloads  and rendering

MHTML.css – all together/*Content-Type: multipart/related; boundary="MYSEPARATOR" --MYSEPARATORContent-Location: myimageContent-Transfer-Encoding: base64 iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAD....U5ErkJggg==--MYSEPARATORContent-Location: anotherContent-Transfer-Encoding: base64 iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAA....U5ErkJggg==--MYSEPARATOR--*/.myclass { background-image:url(mhtml:http://example.org/styles.css!myimage);}.myotherclass { background-image:url(mhtml:http://example.org/styles.css!another);}

Page 85: Progressive downloads  and rendering

MHTML: inline too<!doctype html><html> <head> <title>Look Ma' No HTTP requests</title> <style type="text/css">/*Content-Type: multipart/related; boundary="_"

--_Content-Location:locolocoContent-Transfer-Encoding:base64

iVBOR...CC--_Content-Location:pollolocoContent-Transfer-Encoding:base64

iVBOR....gg==--_--*/.image1 { background-image: url("data:image/png;base64,iVBOR...CC"); /* normal */ *background-image: url(mhtml:http://...html!locoloco); /* IE < 8 */}.image2 { background-image: url("data:image/png;base64,iVBOR...gg=="); /* normal */ *background-image: url(mhtml:http://...html!polloloco); /* IE < 8 */}body { font: bold 24px Arial;} </style> </head> <body> <h1>MHTML + Data:URIs inline in <code>style</code></h1> <p class="image1">hello<br>hello</p> <p class="image2">bonjour<br>bonjour</p> </body></html>

http://phpied.com/inline-mhtml-data-uris/

Page 86: Progressive downloads  and rendering

<!doctype html><html> <head> <title>Look Ma' No HTTP requests</title>

<style type="text/css"> ...

Page 87: Progressive downloads  and rendering

/*Content-Type: multipart/related; boundary="_"

--_Content-Location:locolocoContent-Transfer-Encoding:base64

iVBOR...CC--_Content-Location:pollolocoContent-Transfer-Encoding:base64

iVBOR....gg==--_--*/

Page 88: Progressive downloads  and rendering

.image1 { background-image: url("data:image/png;base64,iVBOR...CC"); /* normal */ *background-image: url(mhtml:http://...html!locoloco); /* IE < 8 */}.image2 { background-image: url("data:image/png;base64,iVBOR...gg=="); /* normal */ *background-image: url(mhtml:http://...html!polloloco); /* IE < 8 */}body { font: bold 24px Arial;}

Page 89: Progressive downloads  and rendering

... </style>

</head> <body> <h1>MHTML + Data:URIs inline in <code>style</code></h1> <p class="image1">hello<br>hello</p> <p class="image2">bonjour<br>bonjour</p> </body></html>

Page 90: Progressive downloads  and rendering

MHTML + data URI• X-browser single request web apps

Page 91: Progressive downloads  and rendering

Single request• WT☠?• Separation of concerns• Content-presentation-behavior• yes, it’s a tradeoff

Page 92: Progressive downloads  and rendering

MHTML + data URI• drawback: repeats the same encoded image• solutions: - browser-specific CSS - keep close = better gzip - or… an ingenious hack

Page 93: Progressive downloads  and rendering

Single stream MHTML/data URI• image header + css + data/9j/4AA0;background-image:url(data:image/jpeg;base64;00,/9j/4AA0

Reality:

IE:

Others:

http://habrahabr.ru/blogs/webdev/90761/

Page 94: Progressive downloads  and rendering

/*Content-Type: multipart/related; boundary="granitza"

--granitzaContent-Type: text/css;

*/#myid {/*--granitzaContent-Location: myimageContent-Transfer-Encoding: base64Content-Type: image/jpeg;*/

/9j/4AA0;background-image:url(data:image/jpeg;base64;00,/9j/4AAQSkZJRgA...);/*--granitzaContent-Type: text/css;

*/background-image: url(mhtml:http://localhost/my.css!myimage) !ie;}/*--granitza--*/

Page 95: Progressive downloads  and rendering

/*Content-Type: multipart/related; boundary="granitza"

--granitzaContent-Type: text/css;

*/#myid {/*--granitzaContent-Location: myimageContent-Transfer-Encoding: base64Content-Type: image/jpeg;*/

/9j/4AA0;background-image:url(data:image/jpeg;base64;00,/9j/4AAQSkZJRgA...);/*--granitzaContent-Type: text/css;

*/background-image: url(mhtml:http://localhost/my.css!myimage) !ie;}/*--granitza--*/

???

Page 96: Progressive downloads  and rendering

/*Content-Type: multipart/related; boundary="granitza"

--granitzaContent-Type: text/css;

*/#myid {/*--granitzaContent-Location: myimageContent-Transfer-Encoding: base64Content-Type: image/jpeg;*/

/9j/4AA0;background-image:url(data:image/jpeg;base64;00,/9j/4AAQSkZJRgA...);/*--granitzaContent-Type: text/css;

*/background-image: url(mhtml:http://localhost/my.css!myimage) !ie;}/*--granitza--*/

Page 97: Progressive downloads  and rendering

/*Content-Type: multipart/related; boundary="granitza"

--granitzaContent-Type: text/css;

*/#myid {/*--granitzaContent-Location: myimageContent-Transfer-Encoding: base64Content-Type: image/jpeg;*/

/9j/4AA0;background-image:url(data:image/jpeg;base64;00,/9j/4AAQSkZJRgA...);/*--granitzaContent-Type: text/css;

*/background-image: url(mhtml:http://localhost/my.css!myimage) !ie;}/*--granitza--*/

???1

2

3

Page 98: Progressive downloads  and rendering

Single stream MHTML/data URI• And for <img> too!

Page 99: Progressive downloads  and rendering

Single stream <img><h2>Hello Kitty</h2><!--granitzaContent-Location: myimageContent-Transfer-Encoding: base64Content-Type: image/gif2 invalid MHTML headers lines followed by data--><![if gt IE 7]><img width="16" height="16" src="data:image/gif;base64,

R0lGODl ... FxMKVvDijNQaodOl+N5Pk+pmIX7brGweCg4SCEhEAOw=="><![endif]>

<!--[if lt IE 8]><img src="mhtml:http://.../bolknote.html!myimage" width="16" height="16"><![endif]-->

<p> more page... </p>

Page 100: Progressive downloads  and rendering

Single stream <img><h2>Hello Kitty</h2><!--granitzaContent-Location: myimageContent-Transfer-Encoding: base64Content-Type: image/gif2 invalid MHTML headers lines followed by data--><![if gt IE 7]><img width="16" height="16" src="data:image/gif;base64,

R0lGODl ... FxMKVvDijNQaodOl+N5Pk+pmIX7brGweCg4SCEhEAOw=="><![endif]>

<!--[if lt IE 8]><img src="mhtml:http://.../bolknote.html!myimage" width="16" height="16"><![endif]-->

<p> more page... </p>

Page 101: Progressive downloads  and rendering

Lazy loading

Page 102: Progressive downloads  and rendering

Lazy loading aka post-loading• After-onload• Some images• Below the fold (on scroll)• Hidden content e.g. tabs

Page 103: Progressive downloads  and rendering
Page 104: Progressive downloads  and rendering
Page 105: Progressive downloads  and rendering

Amazon’s lazy bestsellers • Page’s purpose is ranking• Details can come later• via onload XHR• JS off = no details• but that’s fine (see bullet #1)

Page 106: Progressive downloads  and rendering

Lazy evaluation

Page 107: Progressive downloads  and rendering

GMail mobile’s lazy JS <!doctype html><html><body>...<script id="lazy">/*console.log("I can wait");*/</script>...<script>console.log("I'm needed");window.onload = function () { var comment = document.getElementById('lazy') .innerHTML, code = comment.substring(3, comment.length - 3); eval(code);};</script></body></html> http://googlecode.blogspot.com/2009/09/gmail

-for-mobile-html5-series-reducing.html

Page 108: Progressive downloads  and rendering
Page 109: Progressive downloads  and rendering

Lazy HTML<!doctype html><html><body>...<div id="lazy"><!--<p>lots of html goes here...</p>--></div>...<script>window.onload = function () { var el = document.getElementById('lazy'), inner = el.innerHTML, code = inner.substring(4, inner.length - 3); el.innerHTML = code;};</script></body></html>

http://phpied.com... (coming-soon)

Page 110: Progressive downloads  and rendering

Lazy HTML test• 500K (200K gzipped) HTML doc• “Sherlock Holmes”• comment out 95%• still one whole chapter left

http://www.phpied.com/files/lazyhtml/start.html

Page 111: Progressive downloads  and rendering

Lazy HTML test results

Page 112: Progressive downloads  and rendering

Lazy HTML - misc• Who loads a book?• Use case: blog comments• SEO? Content is hidden• What about display: none?• The test page was simple-to-render, no complex layout

Page 113: Progressive downloads  and rendering

Preloads

Page 114: Progressive downloads  and rendering

Preloads• Anticipate next page• Problems: - does next page anticipate you? - parsing and execution time• <link prefetch="http://..">

Page 115: Progressive downloads  and rendering

Preload sans executevar preload; if (/*@cc_on!@*/false) { // IE preload = function (file) { new Image().src = file; };} else { preload = function (file) { var obj = document.createElement('object'), body = document.body; obj.width = 0; obj.height = 0; obj.data = file; body.appendChild(obj); };}

Page 116: Progressive downloads  and rendering

Preload, then executevar loader = function (file, callback) { var obj = document.createElement('object'), body = document.body; obj.width = 0; obj.height = 0; obj.data = file; obj.onload = function () { var h, js = document.createElement('script'); js.src = file; js.onload = callback; h = document.getElementsByTagName('head')[0]; h.appendChild(js); }; body.appendChild(obj);};

Page 117: Progressive downloads  and rendering

Browser search preload

Page 118: Progressive downloads  and rendering

Chrome search• In-browser search box• Gives suggestions as you type• Visual suggestions in IE8+

Page 119: Progressive downloads  and rendering

IE8 Visual Search Suggestions

...<Item> <Text>Currently: Partly Cloudy, 67F</Text> <Description>High: 71F Low: 63F</Description> <Url>http://weather.yahoo.com/forecast/USCA1024_f.html</Url> <Image source="http://l.yimg.com/a/i/us/we/31/30.gif" alt="Partly Cloudy" width="31" height="31"/></Item>...

Page 120: Progressive downloads  and rendering

IE8 Visual Search Preload

...<Item> <Text>any search suggestion</Text> <Image source="http://path/to/sprite.png" width="0" height="0"/></Item>...

Page 121: Progressive downloads  and rendering

IE8 Visual Search Preload

Page 122: Progressive downloads  and rendering

IE8 Visual Search Preload

• didn’t work for CSS and JS

Page 123: Progressive downloads  and rendering

IE8 Visual Search

• preload images, e.g. sprite• DNS lookups via beacons

Page 124: Progressive downloads  and rendering

Parting words

Page 125: Progressive downloads  and rendering

Do care about• Progressive, non-blocking, asynchronous downloads• Progressive rendering

Page 126: Progressive downloads  and rendering

Thank you!

Stoyan Stefanov@stoyanstefanovhttp://www.phpied.comSlides: http://slideshare.net/stoyan/