Fast Loading JavaScripthttp://www.flickr.com/photos/gaelenh/1443926963/ Velocity EU 2011, @aaronpeters
“ I totallyrock the house!” http://www.flickr.com/photos/jkohen/3799706725/
Lots of JSblocks even more Torstein Frogner
Lots of JSblocks 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
load JS ina non-blocking way 1 scripts execute in order 2 couple external JS with inline JS 3 rendering starts soon; is progressive 5 DOM ready fires asap 4
Reduce risk toa minimum http://www.flickr.com/photos/48329209@N03/4430804547/
Create the bestuser experience! http://www.flickr.com/photos/97469566@N00/4848627841
Normal Script Src<script src =“foo.js" ></script> <script src =“bar.js" ></script> <script> // dependent on bar.js executeAfterBar(); </script>
Chrome’s silly preloadlogic (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!
Why CSPL isa problem Other objects start downloading late It’s against developer intent: bottom BODY means “do it last, other stuff comes first”
Solutions for CSPLMove to top of <body> Move to bottom of <body> Inline the code Add DEFER attribute Add ASYNC attribute Use Script Insertion Keeps 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 +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 isawesome. 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 & jQueryin IE <script defer src =“jquery.js" ></script> <script defer src =“jquery-plugin.js" ></script> ‘ jQuery’ is undefined
Combine jquery.js andjquery-dependent.js if you want DEFER 2 http://www.flickr.com/photos/valeriebb/290711738/
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 = falseImportant! script can’t have document.write
Forget about async=false It’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>
Script loaders likeLABjs can be your best friend. Try it! 5 http://www.flickr.com/photos/valeriebb/290711738/
Execute before StartRender? <2k gzipped? Inline, in <head> Y Couple with inline script? Preserve exec order? N Using jQuery? Combine jquery.js & jquery-dependent.js Other script loaders, like Yepnope, may do an equally good job Y N Normal Script Src, top of <body> Y LABjs Y Dynamic insertion N DEFER Y N Execute right before DCL? N
Somewhat off-topic statementsDon’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!
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 TweetBox <div id =“tbox" ></script> <script> twttr.anywhere( function (T) { T( "#tbox" ).tweetBox(); }); </script> </body> view-source:http://www.cdnplanet.com > jsbeautifier.org ... <script src="http://platform.twitter.com/anywhere.js?id=YOUR_API_KEY&v=1"></script> </head> ...