cs193h: high performance web sites lecture 20: vol 2 – don't scatter inline scripts steve...
TRANSCRIPT
CS193H:High Performance Web Sites
Lecture 20: Vol 2 – Don't Scatter Inline Scripts
Steve SoudersGoogle
announcements11/17 – guest lecturer: Robert Johnson (Facebook), "Fast Data at Massive Scale - lessons learned at Facebook"Handouts of Vol 2 chapters 1-4 are available in class and at office hours. Copies are being sent to SCPD students. DO NOT COPY OR DISTRIBUTE THESE HANDOUTS!
Load scripts without blockingfollow-up from previous lecture:
• ads• Google Analytics• degrading script tags pattern – John Resig
ads and async scriptsmany ads load external scriptswhy can't these scripts be loaded using these non-blocking techniques?
they use document.writeif a script containing document.write is loaded asynchronously, the entire page is erased:
http://stevesouders.com/tests/delayed-script-execution.php(click on "Load Dynamically")
an alternative: Opera's "Delayed Script Execution"
Opera: Delayed Script Execution
opera:config#Delayed%20Script%20Execution
"Primarily for low bandwidth devices, not well-tested on desktop. Ignore script tags until entire document is parsed and rendered, then execute all scripts in order and re-render."renders page without blocking for scriptwhen script executes, document.write is performed where the script occurredgood model for how SCRIPT DEFER should be implemented on all browsers blog post: http://www.stevesouders.com/blog/2008/09/11/delayed-script-execution-in-opera/
Google Analyticshttp://www.google.com/analytics/
"Learn more about where your visitors come from and how they interact with your site."case study: American Cancer Society
http://www.cancer.org/
HTML code:<script type="text/javascript" src="http://www.google-analytics.com/ga.js"></script><script type="text/javascript"> var gaAcctNumber = "UA-144783-1"; var pageTracker = _gat._getTracker(gaAcctNumber); pageTracker._initData(); pageTracker._trackPageview
</script>
how load this asynchronously?
Google Analytics async IEIE:<script defer type="text/javascript" src='http://www.google-analytics.com/ga.js'></script>
<script type="text/javascript">window.onload = function() { var gaAcctNumber = "UA-144783-1"; var pageTracker = _gat._getTracker(gaAcctNumber); pageTracker._initData(); pageTracker._trackPageview; }</script>
Google Analytics async FFFirefox:<script type="text/javascript">var se = document.createElement('script');se.src = 'http://www.google-analytics.com/ga.js';document.getElementsByTagName('head')[0].appendChild(se);window.onload = function() { var gaAcctNumber = "UA-144783-1"; var pageTracker = _gat._getTracker(gaAcctNumber); pageTracker._initData(); pageTracker._trackPageview; }</script>
Google Analytics asyncother techniques:script in iframe
2 requests (iframe and ga.js) instead of 1 (ga.js)could try setting iframe's innerHTML (TBD)
XHR eval and XHR injectiondifferent domains (www.google-analytics.com)
document.writeblocks other resources
script DOM element for IE and FFadd onreadystatechange handler instead of onload
"degrading script tags" pattern – what's that?
Degrading Script Tagsfrom John Resig blog post
http://ejohn.org/blog/degrading-script-tags/
GA example:<script type="text/javascript" src="http://www.google-analytics.com/ga.js">var gaAcctNumber = "UA-144783-1"; var pageTracker = _gat._getTracker(gaAcctNumber); pageTracker._initData(); pageTracker._trackPageview
</script>
no browser supports calling the inlined codeinstead, ga.js would be modified to call it...
Degrading Script Tagsadd to the end of the external script (eg, "ga.js"):var scripts = document.getElementsByTagName("script");
var cntr = scripts.length;
while ( cntr ) {
var curScript = scripts[cntr-1];
if (-1 != curScript.src.indexOf('ga.js')) {
eval( curScript.innerHTML );break;
}
cntr--; // why backwards?
}
wrapping ga.jsyou can't modify ga.jsproxy ga.js on your own serverwrite cronjob to check ga.js Last-Modifiedupdate your proxied version when ga.js changesif you add versioning, you can give your vesion a far future Expires header (ga.js is 7 days)
Firefox 3 and IE download stylesheets in parallel with other resources
http://stevesouders.com/cuzillion/?c0=hc1hfff2_0&c1=hc1hfff2_0&c2=bi1hfff2_0&c3=bf1hfff2_0&c4=bj1hfff2_0
stylesheets are parsed in the order specified, regardless of download order
http://stevesouders.com/hpws2/stylesheets-order.php
same for stylesheets and inline styleshttp://stevesouders.com/hpws2/css-order.php
what about stylesheets and inline scripts?
Stylesheets – ensuring order
Inline scripts blocklong executing inline scripts block rendering and downloads of everything after them in the page
http://stevesouders.com/cuzillion/?c0=bi1hfff1_0&c1=bb0hfff0_5&c2=bi1hfff1_0
workarounds: initiate execution with setTimeout (>250 for FF, nglayout.initialpaint.delay)move JavaScript to external script with advanced downloading techniquesuse Defer attribute (IE only)
Inline script parallelizationresources that occur before an inline script download in parallel while the script executes
http://stevesouders.com/cuzillion/?c0=bi1hfff2_0&c1=bb0hfff0_1&c2=bf2hfff2_0&c3=bb0hfff0_1&c4=bi3hfff2_0
...except for stylesheetshttp://stevesouders.com/cuzillion/?c0=bc1hfff2_0&c1=bb0hfff0_1&c2=bc2hfff2_0&c3=bb0hfff0_1&c4=bi3hfff2_0
why?!CSS and JavaScript might have interdependencies
how might this affect stylesheet and inline script download parallelization?
Stylesheet, inline script Block Downloading
Firefox 3 and IE download stylesheets in parallel with other resources...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 resourcesuse Link, not @import
@import allows the inline script to start and block in IE and FF2http://stevesouders.com/cuzillion/?c0=hc1hfff2_0&c1=hc1hfft2_0&c2=hb0hfff0_3&c3=hj1hfff2_0&t=1227048065109
eBayMSNMySpaceWikipedia
Examples of Scattered Scripts
Don't Scatter Inline Scripts
remember inline scripts carry a cost
avoid long-executing inline scripts
don't put inline scripts between stylesheets and other resources
Homework12/1 11:59pm – Assignment #6 - Improving a Top Site• rules 11-14• Vol 2:
‐ Split the Initial Payload‐ Load Scripts Without Blocking‐ Don't Scatter Inline Scripts‐ Shard Dominant Domains‐ Optimize Images
QuestionsWhat happens if an external script loaded
asynchronously does document.write?How can you load an external script
asynchronously, and have an inline script execute as soon as the external script is loaded?
What do inline scripts block? How can you workaround this blocking?
What's the unusual behaviour of a stylesheet, inline script, and image (in that order)? What would explain why browser developers implemented this behaviour?
How does @import cause downloading problems with stylesheets followed by inline scripts?