Fast Loading JavaScript http://www.flickr.com/photos/gaelenh/ 1443926963/ Velocity EU 2011, @aaronpeters
May 15, 2015
Fast Loading JavaScript
http://www.flickr.com/photos/gaelenh/1443926963/
Velocity EU 2011, @aaronpeters
Better performance==
More revenues
Revisorweb
“I totally rock the house!”
http://www.flickr.com/photos/jkohen/3799706725/
The problem
JavaScript blocks
Lots of JS blocks even more
Torstein Frogner
Lots of JS blocks even more
Torstein Frogner
<script src=“file.js”> blocks parallel downloading in IE8 and Chrome (!)
can’t download subsequent images/iframes
… has “silly preload logic”
2
<script src=“file.js”> and inline scripts block HTML parsing & page rendering
1
http://www.flickr.com/photos/frenkieb/4423393/
Example of bad, bad JS
http://www.flickr.com/photos/frenkieb/4423393/
Example of bad, bad JS
http://www.flickr.com/photos/frenkieb/4423393/
Example of bad, bad JS
Wanna see the horror?
It’s not getting any better
Requirements
load JS in a non-blocking way1
scripts execute in order2
couple external JS with inline JS3
rendering starts soon; is progressive5
DOM ready fires asap4
diskdepot.co.uk
You want to be in control
Reduce risk to a minimum
http://www.flickr.com/photos/48329209@N03/4430804547/
Create the best user experience!
http://www.flickr.com/photos/97469566@N00/4848627841
Async FTW!
http://www.flickr.com/photos/15181848@N02/3742832809
JavaScript Loading Techniques
Normal Script Src
<script src=“foo.js"></script><script src=“bar.js"></script><script>// dependent on bar.jsexecuteAfterBar();</script>
Normal Script Src
Chrome’s silly preload logic
Chrome’s silly preload logic (CSPL)
If there is a non-DEFER, non-ASYNC parser-inserted script in
<head>, Chrome (15) only preloads other parser-inserted
scripts from <body>, not images!
CSPL - Proofin <head> in <body>
Browserscope doesn’t tell you
Browserscope testpage has
script in <body>
Same in IE9?
Nope, all good!
How about FF7?
Yeah, good too!
Why CSPL is a problem
Other objects start downloading late
It’s against developer intent: bottom BODY
means “do it last, other stuff comes first”
Solutions for CSPL
Add DEFER attribute
Add ASYNC attribute
Use Script Insertion
Move to top of <body>
Move to bottom of <body>
Inline the codeKeeps blocking
Start Render
Pre-render blocking JS?- Inline in <head>- External file top of <body>
1
http://www.flickr.com/photos/valeriebb/290711738/
Script Insertion
<script>var d=document, js=d.createElement('script'),
el=d.getElementsByTagName('script')[0];
js.src=“file.js";el.parentNode.insertBefore(js,el);</script>
Script Insertion
Important!script can’t have document.write
Script Insertion + callback()<script>function exec() { renderThingy(); }var d=document, js=d.createElement('script'), el=d.getElementsByTagName('script')[0];js.src=“getsatisfaction.js“;js.done=false; js.onload=function(){ js.done=true,exec() },js.onreadystatechange=function(){("loaded"===js.readyState||"complete"===js.readyState) && !js.done && (js.done=true,exec())};el.parentNode.insertBefore(js,el);</script>
Script insertion is awesome. Make it your default
2
http://www.flickr.com/photos/valeriebb/290711738/
DEFER attribute
<script defer src=“framework.js"></script><script defer src=“app.js"></script>
<script>// dependent on app.js
initApp();</script>
DEFER attribute
Important!script can’t have document.write
DEFER & jQuery in IE
<script defer src=“jquery.js"></script><script defer src=“jquery-plugin.js"></script>
‘jQuery’ is undefined
Combine jquery.js and jquery-dependent.js if you want
DEFER
2
http://www.flickr.com/photos/valeriebb/290711738/
ASYNC attribute
<script async src=“file.js"></script>
ASYNC attribute
Important!script can’t have document.write
Only use async as an ‘add-on’ in dynamic insertion technique
3
http://www.flickr.com/photos/valeriebb/290711738/
ASYNC = false
<script>var d=document, js=d.createElement('script'),
el=d.getElementsByTagName('script')[0];
js.async=false; js.src=“file.js";el.parentNode.insertBefore(js,el);</script> <script async=“false”
src=“file.js"></script>
ASYNC = false
Important!script can’t have document.write
Forget about async=falseIt’s for the far future.
4
http://www.flickr.com/photos/valeriebb/290711738/
LABjs
<script>$LAB .script("framework.js").wait() .script("plugin.framework.js") .wait(function(){ myplugin.init(); framework.init(); });</script>
<script src=“LABjs.js"></script>
LABjs
Important!script can’t have document.write
Script loaders like LABjs can be your best friend. Try it!
5
http://www.flickr.com/photos/valeriebb/290711738/
Execute before Start Render?
<2k gzipped?
Inline, in <head>
Y N
Normal Script Src, top of
<body>
Y
Y
Couple with inline script?
Preserve exec order?
LABjs
Y
Dynamic insertion
N
DEFER
Y
N
Execute right before DCL?N
N
Using jQuery? Combine jquery.js & jquery-dependent.js
Other script loaders, like Yepnope, may do an equally good job
Somewhat off-topic statements
Don’t load it if the page doesn’t need it !
Don’t use jQuery for everything
Do waterfall chart analysis ,‘till you drop Use Webpagetest.org (Firefox 7 coming soon to all
nodes!)
On WPT, use Video capturing to see how it renders
WPT has lots of useful commands in the API. Use them!
Third Party JavaScript
Social buttons BFF!<!-- facebook like --><div class="fb-like" data-send="false" data-
width="280"></div><!-- twitter --><a class="twitter-share-button" data-
count="horizontal">Tweet</a><!-- g+ --><div class="g-plusone" data-size="medium"></div>
http://www.phpied.com/social-button-bffs/
Social buttons BFF!<!-- facebook like --><div class="fb-like" data-send="false" data-
width="280"></div><!-- twitter --><a class="twitter-share-button" data-
count="horizontal">Tweet</a><!-- g+ --><div class="g-plusone" data-size="medium"></div>
http://www.phpied.com/social-button-bffs/
<div id="fb-root"></div><!-- fb needs this --><script>(function(d, s) { var js, fjs = d.getElementsByTagName(s)[0], load =
function(url, id) { if (d.getElementById(id)) {return;} js = d.createElement(s); js.async = js.src = url; js.id = id; fjs.parentNode.insertBefore(js, fjs); }; load('//connect.facebook.net/en_US/all.js#xfbml=1',
'fbjssdk'); load('https://apis.google.com/js/plusone.js',
'gplus1js'); load('//platform.twitter.com/widgets.js', 'tweetjs');}(document, 'script'));</script>
Twitter Anywhere Tweet Box
view-source:http://www.cdnplanet.com > jsbeautifier.org
<div id=“tbox"></script><script>twttr.anywhere(function (T) { T("#tbox").tweetBox(); });</script></body>
...<script src="http://platform.twitter.com/anywhere.js?id=YOUR_API_KEY&v=1"></script>
</head>...
You?
Join the WPO community!You?
You? You?
You?
#webperf http://twitter.com/search#webperf#WPOchat http://www.wpochat.orgPerfplanet http://perfplanet.comMeetup http://web-performance.meetup.com/
http://www.flickr.com/photos/27282406@N03/4134166721/
Questions?http://www.flickr.com/photos/f-oxymoron/5005146417/