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/
Top 10 Most Downloaded Games on Play Store in 2024
Improving 3rd Party Script Performance
1. Improving 3rd Party Script Performance with
<IFRAME>s
Philip Tellis / ptellis@soasta.com
Boston Web Perf / 2013-10-22
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
1
2. • Philip Tellis
• @bluesmoon
• philip@bluesmoon.info
• SOASTA
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
2
6. <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
7. Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
7
9. dynamic script node
1
Loads in parallel with the rest of the page
2
Still blocks the onload event
3
No telling when it will load up
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
9
10. No telling when!
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
10
11. The Method Queue Pattern
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
11
12. 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
13. MQP
var self = this;
_mq = _mq || [];
while(_mq.length) {
// remove the first item from the queue
var params = _mq.shift();
// remove the method from the first item
var method = params.shift();
self[method].apply(self, params);
}
_mq.push = function(params) {
// remove the method from the first item
var method = params.shift();
self[method].apply(self, params);
}
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
13
14. That takes care of #3
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
14
15. But we still block onload
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
15
16. IFRAMEs to the rescue
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
16
17. But IFRAMEs block onload until the subpage has
loaded
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
17
18. (This sub-page intentionally left blank)
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
18
19. So here’s the code – Section I
// Section 1 - Create the iframe
var 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 hurting
screenreaders)
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
19
20. javascript:false is key to solving most
cross-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
21. Except if the page developer sets
document.domain
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
21
22. Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
22
23. The code – Section II
// Section 2 - handle document.domain
try {
// sec exception if document.domain was set
doc = 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
24. Only set document.domain if it has already
been set!
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
24
25. 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
26. Notice that we’ve set document.domain again
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
26
27. This doesn’t work if document.domain is set
after our JavaScript loads
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
27
28. Inside this function, document is the parent
document and this is the iframe!
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
28
29. Also, global variables inside _l() are global to the
parent window
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
29
30. Modify the MQP for IFRAME support
GLOBAL = window;
// Running in an iframe, and our script node’s
// id is js-iframe-async
if(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
31. GLOBAL refers to the parent window and window
refers to the iframe
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
31
32. So attach events to GLOBAL
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
32
33. 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
35. 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
37. We have boomerang set to be cached for 7 days
Cache-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
38. how soon does a new version get to everyone?
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
38
39. hourly on weekends
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
39
40. hourly on weekdays
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
40
41. This is a problem if we have emergency fixes
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
41
42. Cache busting with a far-future expires header
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
42
43. Some more code...
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
43
45. 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 proxies
and Firefox 3.5.11
Note: 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
46. 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
47. reloader.html can be cached forever
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
47
48. Other caching quirks
• Some proxies will ignore all cache control headers and
never clear their cache
• Some user agents have broken clocks, so expiry dates
either never occur or always occur
• Some versions of Chrome have a cache corruption bug so
they 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
49. Old but active versions of boomerang
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
49
50. And the blog post...
http://www.lognormal.com/blog/2012/06/17/moreon-updating-boomerang/
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
50
51. Thank You – Questions?
• Philip Tellis
• @bluesmoon
• philip@bluesmoon.info
• www.SOASTA.com
• boomerang
• LogNormal Blog
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
51
52. Image Credits
• Neutraface Blocks! by David Joyce
http://www.flickr.com/photos/deapeajay/3913282801/
• Stop Hammertime by Rich Anderson
http://www.flickr.com/photos/memestate/54408373/
• This Title Intentionally Left Blank by Jonathan Hinkle
http://www.flickr.com/photos/hynkle/4535749633/
• All other images taken at Velocity 2013 by Philip Tellis and
shared under a Creative Commons Attribution-Share Alike
License.
Boston Web Perf / 2013-10-22
Improving 3rd Party Script Performance with <IFRAME>s
52