Even Faster Web Sites
Steve Souders
[email protected]
http://stevesouders.com/docs/sxsw-20090314.ppt
Disclaimer: This content does not necessarily reflect the opinions of my employer.
the importance of frontend
performance
9%
17%
91%
83%
iGoogle, primed cache
iGoogle, empty cache
time spent on the frontend
www.aol.com
www.ebay.com
www.facebook.com
www.google.com/search
search.live.com/results
www.msn.com
www.myspace.com
en.wikipedia.org/wiki
www.yahoo.com
www.youtube.com
Empty Cache
97%
Primed Cache
97%
95%
95%
47%
81%
81%
0%
67%
98%
98%
94%
0%
94%
98%
91%
97%
98%
96%
97%
April 2008
14 RULES
1. MAKE FEWER HTTP REQUESTS
2. USE A CDN
3. ADD AN EXPIRES HEADER
4. GZIP COMPONENTS
5. PUT STYLESHEETS AT THE TOP
6. PUT SCRIPTS AT THE BOTTOM
7. AVOID CSS EXPRESSIONS
8. MAKE JS AND CSS EXTERNAL
9. REDUCE DNS LOOKUPS
10.MINIFY JS
11.AVOID REDIRECTS
12.REMOVE DUPLICATE SCRIPTS
13.CONFIGURE ETAGS
14.MAKE AJAX CACHEABLE
25% discount code: "ssouders25"
Sept 2007
June 2009
Even Faster Websites
Split the initial payload
Load scripts without blocking
Couple asynchronous scripts
Don't scatter inline scripts
Split the dominant domain
Flush the document early
Use iframes sparingly
Simplify CSS Selectors
Ajax performance (Doug
Crockford)
Writing efficient JavaScript
(Nicholas Zakas)
Creating responsive web apps
(Ben Galbraith, Dion Almaer)
Comet (Dylan Schiemann)
Beyond Gzipping (Tony
Gentilcore)
Optimize Images (Stoyan
Stefanov, Nicole Sullivan)
why focus on JavaScript?
Yahoo!
Wikipedia
eBay
AOL
MySpace
YouTube
Facebook
scripts block
<script src="A.js"> blocks parallel
downloads and rendering
http://stevesouders.com/cuzillion/?ex=10008
MSN.com: parallel scripts
MSN
Scripts and other resources downloaded
in parallel! How? Secret sauce?!
var p=
g.getElementsByTagName("HEAD")[0];
var c=g.createElement("script");
c.type="text/javascript";
c.onreadystatechange=n;
c.onerror=c.onload=k;
c.src=e;
p.appendChild(c)
asynchronous script loading
XHR Eval
XHR Injection
Script in Iframe
Script DOM Element
Script Defer
document.write Script Tag
XHR Eval
var xhrObj = getXHRObject();
xhrObj.onreadystatechange =
function() {
if ( xhrObj.readyState != 4 ) return;
eval(xhrObj.responseText);
};
xhrObj.open('GET', 'A.js', true);
xhrObj.send('');
script must have same domain as main page
must refactor script
http://stevesouders.com/cuzillion/?ex=10009
XHR Injection
var xhrObj = getXHRObject();
xhrObj.onreadystatechange =
function() {
if ( xhrObj.readyState != 4 ) return;
var se=document.createElement('script');
document.getElementsByTagName('head')
[0].appendChild(se);
se.text = xhrObj.responseText;
};
xhrObj.open('GET', 'A.js', true);
xhrObj.send('');
script must have same domain as main page
http://stevesouders.com/cuzillion/?ex=10015
Script in Iframe
<iframe src='A.html' width=0 height=0
frameborder=0 id=frame1></iframe>
iframe must have same domain as main page
must refactor script:
// access iframe from main page
window.frames[0].createNewDiv();
// access main page from iframe
parent.document.createElement('div');
http://stevesouders.com/cuzillion/?ex=10012
Script DOM Element
var se = document.createElement('script');
se.src = 'http://anydomain.com/A.js';
document.getElementsByTagName('head')[0]
.appendChild(se);
script and main page domains can differ
no need to refactor JavaScript
http://stevesouders.com/cuzillion/?ex=10010
Script Defer
<script defer src='A.js'></script>
only supported in IE (just landed in FF 3.1)
script and main page domains can differ
no need to refactor JavaScript
http://stevesouders.com/cuzillion/?ex=10013
document.write Script Tag
document.write("<scr" +
"ipt type='text/javascript' src='A.js'>" +
"</scr" + "ipt>");
parallelization only works in IE
parallel downloads for scripts, nothing else
all document.writes must be in same
script block
http://stevesouders.com/cuzillion/?ex=10014
load scripts without blocking
||
domains
existing browser ensures
downcan
scripts
busy
order
loads
differ
normal Script Src
XHR Eval
XHR Injection
Script in Iframe
Script DOM Element
Script Defer
document.write
Script Tag
*Only
size
(bytes)
no
yes
yes
IE,FF
IE,FF
~50
IE,FF
no
no
no
no
~500
IE,FF
no
yes
no
no
~500
IE,FF
no
no
IE,FF
no
~50
IE,FF
yes
yes
FF
FF
~200
IE
yes
yes
IE,FF
IE
~50
IE*
yes
yes
IE,FF
IE
~100
other document.write scripts are downloaded in parallel (in the same script block).
asynchronous JS example: menu.js
script DOM element approach
<script type="text/javascript">
var domscript = document.createElement('script');
domscript.src = "menu.js";
document.getElementsByTagName('head')[0].appendChild(domscri
pt);
var aExamples =
[
['couple-normal.php', 'Normal Script Src'],
['couple-xhr-eval.php', 'XHR Eval'],
...
['managed-xhr.php', 'Managed XHR']
];
function init() {
EFWS.Menu.createMenu('examplesbtn', aExamples);
}
init();
</script>
before
after
load scripts without blocking
||
domains
existing browser ensures
downcan
scripts
busy
order
loads
differ
normal Script Src
XHR Eval
XHR Injection
Script in Iframe
Script DOM Element
Script Defer
document.write
Script Tag
*Only
size
(bytes)
no
yes
yes
IE,FF
IE,FF
~50
IE,FF
no
no
no
no
~500
IE,FF
no
yes
no
no
~500
IE,FF
no
no
IE,FF
no
~50
IE,FF
yes
yes
FF
IE
yes
yes
IE,FF
FF !IE ~200
IE
~50
IE*
yes
yes
IE,FF
IE
other document.write scripts are downloaded in parallel (in the same script block).
~100
what about
inlined code
that depends on the script?
coupling techniques
hardcoded callback
window onload
timer
degrading script tags
script onload
technique 5: script onload
<script type="text/javascript">
var aExamples = [['couple-normal.php', 'Normal Script Src'], ...];
function init() {
EFWS.Menu.createMenu('examplesbtn', aExamples);
}
var domscript = document.createElement('script');
domscript.src = "menu.js";
domscript.onloadDone = false;
domscript.onload = function() {
if ( ! domscript.onloadDone ) { init(); }
domscript.onloadDone = true;
};
domscript.onreadystatechange = function() {
if ( "loaded" === domscript.readyState ) {
if ( ! domscript.onloadDone ) { init(); }
domscript.onloadDone = true;
}
}
document.getElementsByTagName('head')[0].appendChild(domscript);
</script>
pretty nice, medium complexity
case study: Google Analytics
recommended pattern:
1
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ?
"https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost +
"google-analytics.com/ga.js'
type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-xxxxxx-x");
pageTracker._trackPageview();
</script>
document.write Script Tag approach
blocks other resources
1http://www.google.com/support/analytics/bin/answer.py?hl=en&answer=55488
case study: dojox.analytics.Urchin
1
_loadGA: function(){
var gaHost = ("https:" == document.location.protocol) ?
"https://ssl." : "http://www.";
dojo.create('script', {
src: gaHost + "google-analytics.com/ga.js"
}, dojo.doc.getElementsByTagName("head")[0]);
setTimeout(dojo.hitch(this, "_checkGA"), this.loadInterval);
},
_checkGA: function(){
setTimeout(dojo.hitch(this, !window["_gat"] ? "_checkGA" :
"_gotGA"), this.loadInterval);
},
_gotGA: function(){
this.tracker = _gat._getTracker(this.acct); ...
}
Script DOM Element approach
"timer" coupling technique (script onload better)
1http://docs.dojocampus.org/dojox/analytics/Urchin
asynchronous loading & coupling
async technique: Script DOM Element
– easy, cross-browser
– doesn't ensure script order
coupling technique: script onload
– fairly easy, cross-browser
– ensures execution order for external script
and inlined code
bad: stylesheet followed by
inline script
browsers download stylesheets in parallel
with other resources that follow...
...unless the stylesheet is followed by an
inline script
http://stevesouders.com/cuzillion/?ex=10021
best to move inline scripts above
stylesheets or below other resources
use Link, not @import
don't scatter inline scripts
MSN
Wikipedia
eBay
MySpace
iframes:
most expensive DOM element
load 100 empty elements
of each type
tested in all major
1
browsers
1IE
6, 7, 8; FF 2, 3.0, 3.1b2; Safari 3.2, 4; Opera 9.63, 10; Chrome 1.0, 2.0
iframes block onload
parent's onload doesn't fire until iframe and
all its components are downloaded
workaround for Safari and Chrome: set
iframe src in JavaScript
<iframe id=iframe1 src=""></iframe>
<script type="text/javascript">
document.getElementById('iframe1').src="url";
</script>
scripts block iframe
IE
script
Firefox
script
Safari
Chrome
Opera
script
no surprise – scripts in the parent block
the iframe from loading
stylesheets block iframe (IE, FF)
IE
stylesheet
Firefox
stylesheet
Safari
Chrome
Opera
stylesheet
surprise – stylesheets in the parent block
the iframe or its resources in IE & Firefox
stylesheets after iframe still block (FF)
IE
Firefox
Safari
Chrome
Opera
stylesheet
stylesheet
stylesheet
surprise – even moving the stylesheet after
the iframe still causes the iframe's
resources to be blocked in Firefox
iframes: no free connections
parent
iframe
iframe shares connection pool with parent
(here – 2 connections per server in IE 7)
flush the document early
html
image
image
script
html
image
image
script
call PHP's flush()
gotchas:
–
–
–
–
–
PHP output_buffering – ob_flush()
Transfer-Encoding: chunked
gzip – Apache's DeflateBufferSize before 2.2.8
proxies and anti-virus software
browsers – Safari (1K), Chrome (2K)
other languages:
$| or FileHandle autoflush (Perl), flush
(Python), ios.flush (Ruby)
flushing and domain blocking
you might need to move flushed resources to
a domain different from the HTML doc
blocked by HTML document
html
image
image
script
html
image
image
script
different domains
case study: Google search
google
image
image
script
image
204
takeaways
focus on the frontend
run YSlow: http://developer.yahoo.com/yslow
this year's focus: JavaScript
speed matters
impact on revenue
Google: +500 ms  -20% traffic1
Yahoo: +400 ms  -5-9% full-page traffic
Amazon: +100 ms  -1% sales1
http://home.blarg.net/~glinden/StanfordDataMining.2006-11-29.ppt
2 http://www.slideshare.net/stoyan/yslow-20-presentation
1
2
cost savings
hardware – reduced load
bandwidth – reduced response size
http://billwscott.com/share/presentations/2008/stanford/HPWP-RealWorld.pdf
if you want
better user experience
more revenue
reduced operating expenses
the strategy is clear
Even Faster Web Sites
Steve Souders
[email protected]
http://stevesouders.com/docs/sxsw-20090314.ppt
Descargar

High Performance Web Sites 14 rules for faster