More Related Content Similar to Progressive downloads and rendering (Stoyan Stefanov) Similar to Progressive downloads and rendering (Stoyan Stefanov) (20) Progressive downloads and rendering (Stoyan Stefanov)12. Durations
actual
expected
perceived
rem’d
time
13. It feels slower when…
• Unpleasant
• Unknown
• Boring
• Too much to keep track
17. The basics
• Reducing the # HTTP
• Gzip
• Minification
• Image smushing
• Expires
• CDN
18. The basics
• Yahoo!’s best practices +
YSlow
http://developer.yahoo.com/performance/
• Google’s too +
Page Speed
http://code.google.com/speed/
24. Agenda
1. Prevent download blocks:
scripts, styles, CC, favicon
2. Ways to render sooner:
flush, data URIs, lazy loading,
lazy evaluation, preloading,
animations
27. 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>
30. Non-blocking JavaScript
• deferand async
• Defer: IE innovation, ok to
delay, but keep order
• Async: HTML5, whatever
<script asyncsrc="my.js" onload="doIt()"></script>
<script defer src="my.js" onload="doIt()"></script>
32. Non-blocking JavaScript
• Asynchronous loading
html
js
png
png
varh, js= document.createElement('script');
js.src = 'myscript.js';
h= document.getElementsByTagName('head')[0];
h.appendChild(js);
36. 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/
41. 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
45. 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]-->
48. Solution for case #2
<!--[if IE 6]>
<html class="ie6">
<![endif]-->
<!--[if !IE]><!-->
<html>
<!--<![endif]-->
54. Chunked encoding
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
25
This is the data in the first chunk
1C
and this is the second one
0
60. HTTP chunking: not only HTML
• Google Instant
• /**/ - delimited JSON
pieces
• Chunk #1 suggestions
• Chunk #2 results
http://tinyurl.com/chunkview
62. Fewer HTTP requests
• Inline images:
in CSS sprites
with data: URI scheme
http://csssprites.com
http://spriteme.org
63. Fewer HTTP requests
• data: URI scheme
$ php -r echo base64_encode(file_get_contents('my.png'));”
iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAGElEQVQIW2P4
DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC
81. 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/
82. MHTML - one part
Content-Location: myimage
Content-Transfer-Encoding: base64
iVBORw0KGgoAAAANSU....U5ErkJggg==
83. MHTML - multi parts
Content-Type: multipart/related; boundary=MYSEPARATOR
--MYSEPARATOR
[here comes part one] The
double-
--MYSEPARATOR dash of
doom
[here's part two]
--MYSEPARATOR--
84. MHTML.css – all together
/*
Content-Type: multipart/related; boundary=MYSEPARATOR
--MYSEPARATOR
Content-Location: myimage
Content-Transfer-Encoding: base64
iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAD....U5ErkJggg==
--MYSEPARATOR
Content-Location: another
Content-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);
}
85. MHTML: inline too
!doctype html
html
head
titleLook Ma' No HTTP requests/title
style type=text/css
/*
Content-Type: multipart/related; boundary=_
--_
Content-Location:locoloco
Content-Transfer-Encoding:base64
iVBOR...CC
--_
Content-Location:polloloco
Content-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
h1MHTML + Data:URIs inline in codestyle/code/h1
p class=image1hellobrhello/p http://phpied.com
p class=image2bonjourbrbonjour/p
/body
/html
/inline-mhtml-data-uris/
88. .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;
}
92. MHTML + data URI
• drawback: repeats the same
encoded image
• solutions:
- browser-specific CSS
- keep close = better gzip
- or… an ingenious hack
93. 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/
94. /*
Content-Type: multipart/related; boundary=granitza
--granitza
Content-Type: text/css;
*/
#myid {
/*
--granitza
Content-Location: myimage
Content-Transfer-Encoding: base64
Content-Type: image/jpeg;*/
/9j/4AA0;background-image:url(data:image/jpeg;base64;00,/9j/4AAQSkZJRgA...);
/*
--granitza
Content-Type: text/css;
*/
background-image: url(mhtml:http://localhost/my.css!myimage) !ie;
}
/*
--granitza--
*/
95. /*
Content-Type: multipart/related; boundary=granitza
--granitza
Content-Type: text/css;
*/
???
#myid {
/*
--granitza
Content-Location: myimage
Content-Transfer-Encoding: base64
Content-Type: image/jpeg;*/
/9j/4AA0;background-image:url(data:image/jpeg;base64;00,/9j/4AAQSkZJRgA...);
/*
--granitza
Content-Type: text/css;
*/
background-image: url(mhtml:http://localhost/my.css!myimage) !ie;
}
/*
--granitza--
*/
96. /*
Content-Type: multipart/related; boundary=granitza
--granitza
Content-Type: text/css;
*/
#myid {
/*
--granitza
Content-Location: myimage
Content-Transfer-Encoding: base64
Content-Type: image/jpeg;*/
/9j/4AA0;background-image:url(data:image/jpeg;base64;00,/9j/4AAQSkZJRgA...);
/*
--granitza
Content-Type: text/css;
*/
background-image: url(mhtml:http://localhost/my.css!myimage) !ie;
}
/*
--granitza--
*/
97. /*
Content-Type: multipart/related; boundary=granitza
--granitza
Content-Type: text/css;
*/ 1 ???
#myid {
/*
--granitza
Content-Location: myimage
2
Content-Transfer-Encoding: base64
Content-Type: image/jpeg;*/
/9j/4AA0;background-image:url(data:image/jpeg;base64;00,/9j/4AAQSkZJRgA...);
/*
--granitza
Content-Type: text/css;
*/
background-image: url(mhtml:http://localhost/my.css!myimage) !ie;
3
}
/*
--granitza--
*/
99. Single stream img
h2Hello Kitty/h2
!
--granitza
Content-Location: myimage
Content-Transfer-Encoding: base64
Content-Type: image/gif
2 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]
imgsrc=mhtml:http://.../bolknote.html!myimage width=16 height=16
![endif]--
p more page... /p
100. Single stream img
h2Hello Kitty/h2
!
--granitza
Content-Location: myimage
Content-Transfer-Encoding: base64
Content-Type: image/gif
2 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]
imgsrc=mhtml:http://.../bolknote.html!myimage width=16 height=16
![endif]--
p more page... /p
102. Lazy loading aka post-loading
• After-onload
• Some images
• Below the fold (on scroll)
• Hidden content e.g. tabs
105. 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)
107. GMail mobile’s lazy JS
!doctype html
htmlbody
...
scriptid=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 http://googlecode.blogspot.com/2009/09
/body/html /gmail-for-mobile-html5-series-reducing.html
109. Lazy HTML
!doctype html
htmlbody
...
divid=lazy!--
plots 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)
110. 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
112. 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
114. Preloads
• Anticipate next page
• Problems:
- does next page anticipate you?
- parsing and execution time
•link prefetch=http://..
115. Preload sans execute
varpreload;
if (/*@cc_on!@*/false) { // IE
preload = function (file) {
new Image().src = file;
};
} else {
preload = function (file) {
varobj = document.createElement('object'),
body = document.body;
obj.width = 0;
obj.height = 0;
obj.data = file;
body.appendChild(obj);
};
}
116. Preload, then execute
varloader = function (file, callback) {
varobj = document.createElement('object'),
body = document.body;
obj.width = 0;
obj.height = 0;
obj.data = file;
obj.onload = function () {
varh,js= document.createElement('script');
js.src =file;
js.onload=callback;
h = document.getElementsByTagName('head')[0];
h.appendChild(js);
};
body.appendChild(obj);
};
119. IE8 Visual
Search Suggestions
...
Item
TextCurrently: Partly Cloudy, 67F/Text
DescriptionHigh: 71F Low: 63F/Description
Urlhttp://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
...
120. IE8 Visual Search Preload
...
Item
Textany search suggestion/Text
Image
source=http://path/to/sprite.png
width=0
height=0/
/Item
...
125. Do care about
• Progressive,
non-blocking,
asynchronous downloads
• Progressive rendering
Editor's Notes c Dev process, philosophy Non-blockingasynchronousFree-falling waterfalls Rendering something quickly ~200ms - instanteneous redesign c c c c - 3 times faster on 3G, 4 and 1/2 times faster on WiFi - still faster after evaluation - DOMContentLoaded happens sooner S S S S S Showing something in 200 ms is incredible, users will love it