Upload
philip-tellis
View
7.076
Download
2
Tags:
Embed Size (px)
DESCRIPTION
Learn how 3rd party script authors can make their scripts perform better and cause less trouble for host pages. http://www.meetup.com/Web-Performance-Boston/events/143640602/
Citation preview
Improving 3rd Party Script Performance with<IFRAME>s
Philip Tellis / [email protected]
Boston Web Perf / 2013-10-22
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 1
• Philip Tellis• @bluesmoon• [email protected]• SOASTA
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 2
1Loading JavaScript
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 3
Do you use JavaScript?
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 4
<script src="..."></script>
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 5
<script src>
• Works well with browser lookahead• But blocks everything• Yes, you can use async or defer
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 6
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 7
document.createElement("script");
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 8
dynamic script node
1 Loads in parallel with the rest of the page2 Still blocks the onload event3 No telling when it will load up
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 9
No telling when!
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 10
The Method Queue Pattern
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 11
MQP
var _mq = _mq || [];
var s = document.createElement("script"),t = document.getElementsByTagName("script")[0];
s.src="http://some.site.com/script.js";t.parentNode.insertBefore(s, t);
// script.js will be available some time in the// future, but we can call its methods
_mq.push(["method1", list, of, params]);_mq.push(["method2", other, params]);
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 12
MQP
var self = this;_mq = _mq || [];while(_mq.length) {
// remove the first item from the queuevar params = _mq.shift();// remove the method from the first itemvar method = params.shift();
self[method].apply(self, params);}
_mq.push = function(params) {// remove the method from the first itemvar method = params.shift();
self[method].apply(self, params);}
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 13
That takes care of #3
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 14
But we still block onload
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 15
IFRAMEs to the rescue
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 16
But IFRAMEs block onload until the subpage hasloaded
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 17
(This sub-page intentionally left blank)
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 18
So here’s the code – Section I
// Section 1 - Create the iframevar dom,doc,where,
iframe = document.createElement("iframe");
iframe.src = "javascript:false";iframe.title = ""; iframe.role = "presentation";(iframe.frameElement || iframe).style.cssText =
"width: 0; height: 0; border: 0";
where = document.getElementsByTagName("script");where = where[where.length - 1];where.parentNode.insertBefore(iframe, where);
(Note that we set iframe.title and iframe.role to avoid hurtingscreenreaders)
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 19
javascript:false is key to solving mostcross-domain issues
about:blank is problematic on IE6 with SSL
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 20
Except if the page developer setsdocument.domain
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 21
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 22
The code – Section II
// Section 2 - handle document.domaintry {
// sec exception if document.domain was setdoc = iframe.contentWindow.document;
}catch(e) {
dom = document.domain;iframe.src =
"javascript:var d=document.open();" +"d.domain=’" + dom + "’;" +"void(0);";
doc = iframe.contentWindow.document;}
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 23
Only set document.domain if it has alreadybeen set!
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 24
The code – Section III
// Section 3 - tell the iframe to load our script
doc.open()._l = function() {var js = this.createElement("script");if(dom)
this.domain = dom;js.id = "js-iframe-async";js.src = script_url;this.body.appendChild(js);
};
doc.write(’<body onload="document._l();">’);doc.close();
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 25
Notice that we’ve set document.domain again
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 26
This doesn’t work if document.domain is setafter our JavaScript loads
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 27
Inside this function, document is the parentdocument and this is the iframe!
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 28
Also, global variables inside _l() are global to theparent window
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 29
Modify the MQP for IFRAME support
GLOBAL = window;
// Running in an iframe, and our script node’s// id is js-iframe-asyncif(window.parent != window &&
document.getElementById("js-iframe-async")) {
GLOBAL = window.parent;}
GLOBAL._mq = GLOBAL._mq || [];_mq = GLOBAL._mq;
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 30
GLOBAL refers to the parent window and windowrefers to the iframe
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 31
So attach events to GLOBAL
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 32
Summary (part 1)
• Create an iframe with src set to javascript:false
• Set document.domain if needed (twice)• Write dynamic script node into iframe on iframe’s onload
event• Alias parent window into iframe
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 33
Result: Happy Customers
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 34
Read all about it
• http://lognormal.com/blog/2012/12/12/the-script-loader-pattern/
• https://www.w3.org/Bugs/Public/show_bug.cgi?id=21074
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 35
2Cache Behaviour
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 36
We have boomerang set to be cached for 7 daysCache-Control: max-age=604800,
stale-while-revalidate=60, stale-if-error=3600
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 37
how soon does a new version get to everyone?
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 38
hourly on weekends
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 39
hourly on weekdays
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 40
This is a problem if we have emergency fixes
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 41
Cache busting with a far-future expires header
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 42
Some more code...
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 43
location.reload(true);
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 44
More completely
<script src="SCRIPT.js"></script><script>var reqd_ver = location.search;
window.onload = function() {var ver = SCRIPT.version;if (ver < reqd_ver) { // or use semver
location.reload(true);}
};</script>
The condition protects us from an infinite loop with bad proxiesand Firefox 3.5.11Note: Don’t use location.hash – it messes with history on IE8.
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 45
Add this in an iframe after onload using//url.to/reloader.html?1.2.3
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 46
reloader.html can be cached forever
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 47
Other caching quirks
• Some proxies will ignore all cache control headers andnever clear their cache
• Some user agents have broken clocks, so expiry dateseither never occur or always occur
• Some versions of Chrome have a cache corruption bug sothey might start up with an empty cache
• Cache-control headers are honoured by pre-browsing
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 48
Old but active versions of boomerang
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 49
And the blog post...
http://www.lognormal.com/blog/2012/06/17/more-on-updating-boomerang/
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 50
Thank You – Questions?
• Philip Tellis• @bluesmoon• [email protected]• www.SOASTA.com• boomerang• LogNormal Blog
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 51
Image Credits
• Neutraface Blocks! by David Joycehttp://www.flickr.com/photos/deapeajay/3913282801/
• Stop Hammertime by Rich Andersonhttp://www.flickr.com/photos/memestate/54408373/
• This Title Intentionally Left Blank by Jonathan Hinklehttp://www.flickr.com/photos/hynkle/4535749633/
• All other images taken at Velocity 2013 by Philip Tellis andshared under a Creative Commons Attribution-Share AlikeLicense.
Boston Web Perf / 2013-10-22 Improving 3rd Party Script Performance with <IFRAME>s 52