steve souders [email protected] even faster web sites disclaimer: this content does not...
TRANSCRIPT
![Page 1: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/1.jpg)
Steve [email protected]
http://stevesouders.com/docs/sxsw-20090314.ppt
Even Faster Web Sites
Disclaimer: This content does not necessarily reflect the opinions of my employer.
![Page 2: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/2.jpg)
17%
83%
iGoogle, primed cache
the importance of frontend performance
9% 91%
iGoogle, empty cache
![Page 3: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/3.jpg)
time spent on the frontend
Empty Cache
Primed Cache
www.aol.com 97% 97%
www.ebay.com 95% 81%
www.facebook.com 95% 81%
www.google.com/search
47% 0%
search.live.com/results 67% 0%
www.msn.com 98% 94%
www.myspace.com 98% 98%
en.wikipedia.org/wiki 94% 91%
www.yahoo.com 97% 96%
www.youtube.com 98% 97%April 2008
![Page 4: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/4.jpg)
14 RULES
1. MAKE FEWER HTTP REQUESTS
2. USE A CDN3. ADD AN EXPIRES HEADER4. GZIP COMPONENTS5. PUT STYLESHEETS AT THE
TOP6. PUT SCRIPTS AT THE
BOTTOM7. AVOID CSS EXPRESSIONS8. MAKE JS AND CSS
EXTERNAL9. REDUCE DNS LOOKUPS10.MINIFY JS11.AVOID REDIRECTS12.REMOVE DUPLICATE
SCRIPTS13.CONFIGURE ETAGS14.MAKE AJAX CACHEABLE
![Page 5: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/5.jpg)
![Page 6: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/6.jpg)
![Page 7: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/7.jpg)
![Page 8: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/8.jpg)
25% discount code: "ssouders25"
![Page 9: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/9.jpg)
Sept 2007
![Page 10: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/10.jpg)
June 2009
![Page 11: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/11.jpg)
Even Faster Websites
Split the initial payloadLoad scripts without
blockingCouple asynchronous scripts
Don't scatter inline scriptsSplit the dominant
domainFlush 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)
![Page 12: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/12.jpg)
AOLeBayFacebookMySpaceWikipediaYahoo!
why focus on JavaScript?
YouTube
![Page 13: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/13.jpg)
scripts block
<script src="A.js"> blocks parallel downloads and rendering
http://stevesouders.com/cuzillion/?ex=10008
![Page 14: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/14.jpg)
MSNScripts 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)
MSN.com: parallel scripts
![Page 15: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/15.jpg)
asynchronous script loading
XHR Eval
XHR Injection
Script in Iframe
Script DOM Element
Script Defer
document.write Script Tag
![Page 16: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/16.jpg)
XHR Eval
script must have same domain as main page
must refactor script
var xhrObj = getXHRObject();xhrObj.onreadystatechange = function() { if ( xhrObj.readyState != 4 ) return; eval(xhrObj.responseText); };xhrObj.open('GET', 'A.js', true);xhrObj.send('');
http://stevesouders.com/cuzillion/?ex=10009
![Page 17: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/17.jpg)
XHR Injectionvar 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 pagehttp://stevesouders.com/cuzillion/?ex=10015
![Page 18: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/18.jpg)
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 pagewindow.frames[0].createNewDiv();
// access main page from iframeparent.document.createElement('div');
http://stevesouders.com/cuzillion/?ex=10012
![Page 19: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/19.jpg)
Script DOM Elementvar 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
![Page 20: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/20.jpg)
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
![Page 21: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/21.jpg)
document.write Script Tagdocument.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
![Page 22: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/22.jpg)
load scripts without blocking
*Only other document.write scripts are downloaded in parallel (in the same script block).
![Page 23: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/23.jpg)
![Page 24: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/24.jpg)
asynchronous JS example: menu.js
<script type="text/javascript">var domscript = document.createElement('script');domscript.src = "menu.js"; document.getElementsByTagName('head')
[0].appendChild(domscript);
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>
script DOM element approach
![Page 25: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/25.jpg)
before
after
![Page 26: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/26.jpg)
load scripts without blocking
*Only other document.write scripts are downloaded in parallel (in the same script block).
!IE
![Page 27: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/27.jpg)
what about
inlined code that depends on the script?
![Page 28: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/28.jpg)
coupling techniques
hardcoded callback
window onload
timer
degrading script tags
script onload
![Page 29: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/29.jpg)
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
![Page 30: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/30.jpg)
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
![Page 31: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/31.jpg)
case study: dojox.analytics.Urchin1
_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
![Page 32: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/32.jpg)
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
![Page 33: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/33.jpg)
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
![Page 34: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/34.jpg)
eBayMSNMySpaceWikipedia
don't scatter inline scripts
![Page 35: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/35.jpg)
iframes: most expensive DOM element
load 100 empty elements of each type
tested in all major browsers1
1IE 6, 7, 8; FF 2, 3.0, 3.1b2; Safari 3.2, 4; Opera 9.63, 10; Chrome 1.0, 2.0
![Page 36: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/36.jpg)
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>
![Page 37: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/37.jpg)
scripts block iframe
no surprise – scripts in the parent block the iframe from loading
IE
Firefox
Safari Chrome
Opera
script
script
script
![Page 38: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/38.jpg)
stylesheets block iframe (IE, FF)
surprise – stylesheets in the parent block the iframe or its resources in IE & Firefox
IE
Firefox
Safari Chrome
Opera
stylesheet
stylesheet
stylesheet
![Page 39: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/39.jpg)
stylesheets after iframe still block (FF)
surprise – even moving the stylesheet after the iframe still causes the iframe's resources to be blocked in Firefox
IE
Firefox
Safari Chrome
Opera
stylesheet
stylesheet
stylesheet
![Page 40: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/40.jpg)
iframes: no free connections
iframe shares connection pool with parent (here – 2 connections per server in IE 7)
iframe
parent
![Page 41: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/41.jpg)
flush the document early
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)
htmlimageimagescript
htmlimageimagescript call PHP's flush()
![Page 42: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/42.jpg)
flushing and domain blocking
you might need to move flushed resources to a domain different from the HTML dochtml
imageimagescript
htmlimageimagescript
googleimageimagescriptimage204
case study: Google search
blocked by HTML document
different domains
![Page 43: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/43.jpg)
takeaways
focus on the frontend
run YSlow: http://developer.yahoo.com/yslow
this year's focus: JavaScript
speed matters
![Page 44: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/44.jpg)
impact on revenue
Google:
Yahoo:
Amazon:
1 http://home.blarg.net/~glinden/StanfordDataMining.2006-11-29.ppt2 http://www.slideshare.net/stoyan/yslow-20-presentation
+500 ms -20% traffic1
+400 ms -5-9% full-page traffic2
+100 ms -1% sales1
![Page 45: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/45.jpg)
cost savings
hardware – reduced load
bandwidth – reduced response size
http://billwscott.com/share/presentations/2008/stanford/HPWP-RealWorld.pdf
![Page 46: Steve Souders souders@google.com Even Faster Web Sites Disclaimer: This content does not necessarily reflect](https://reader036.vdocuments.site/reader036/viewer/2022062618/5514660c550346414e8b5b74/html5/thumbnails/46.jpg)
if you want better user experience more revenue reduced operating expenses
the strategy is clear
Even Faster Web Sites