thread. This includes the downloading* and execution of Javascript. * Modern browsers download multiple resources at the same time, offsetting this issue somewhat. Tuesday, May 1, 12
page rendering while executing </script> </head> <body> <h1>Welcome to my super-awesome page!</h1> <script> // Any inline code will also block page rendering </script> <!-- Mind-blowing content here --> … </body> </html> Inline code inserted in the head or body of the page will block the loading of assets that follow, and the rendering of the page, until the script has fully loaded and executed. Tuesday, May 1, 12
block asset loading and page rendering until it is done --> <script src=“my_special_scripts.js”></script> </head> <body> <h1>Welcome to my super-awesome page!</h1> <!-- Mind-blowing content here --> … </body> </html> External scripts have the same issue. In fact, they can be worse, as they require an extra HTTP request to load. Tuesday, May 1, 12
grinds to a halt. If you have a lot of Javascript executing in the <head> or inline, the page will be perceived as slow. And slow is BAD.* * http://googleresearch.blogspot.com/2009/06/speed-matters.html Tuesday, May 1, 12
Mind-blowing content here --> … <!-- This script will block, but it’s less of an issue because the DOM has already been loaded --> <script src=“my_special_scripts.js”></script> </body> </html> This technique doesn’t really prevent Javascript from blocking; it just defers the loading and execution until the rest of the page has loaded . Tuesday, May 1, 12
element created via the createElement() DOM method and inserted into the page DOM via insertBefore(). This is the method used by Google Analytics to load its tracking code without blocking the page. Tuesday, May 1, 12
block --> <script> var js = document.createElement(“script”), base = document.getElementsByTagName(“script”)[0] js.async = true js.src = "script.js” base.parentNode.insertBefore(js, base) </script> </head> <body> <h1>Welcome to my super-awesome page!</h1> … </body> </html> In this example, script.js is loaded asynchronously via an inject script element. Note that the injection script will block! Tuesday, May 1, 12
execution of scripts in a non-blocking fashion. Most loaders offer both asynchronous loading and control of execution, plus callbacks to fire off code based on loaded scripts. Tuesday, May 1, 12
block --> <script src=“head.js”></script> <script> // fire off some code when all scripts are loaded head.ready(function() { // Note the call to jQuery, which isn’t loaded. Cool. $(“#element”).show(); }) // Load jQuery asychronously head.js(“/path/to/jquery.js”) </script> </head> <body> … Loading an external script with head.js is pretty simple. Note the we can call unloaded library code with head.ready(). Tuesday, May 1, 12
loader implementations. Not every loader is ideal for all situations. For a comparison of load speeds of various loaders, check out http://artzstudio.com/files/Boot/test/benchmarks/script.html Tuesday, May 1, 12
element. This attribute has been around for a while for IE, and was added to FireFox a while ago. Support is good across modern browsers*. External scripts† using either of these will be loaded and execute in a non-blocking manner. * caniuse.com/#search=async | defer † Scripts loaded with the src attribute. Tuesday, May 1, 12
the script asynchronously and execute is after the DOM is ready. Execution order is determined by source order. <!DOCTYPE html> <html> <head> <!-- This script won’t block and will be executed when the DOM is ready --> <script src=“jquery.min.js” defer></script> </head> <body> <h1>Welcome to my super-awesome page!</h1> <!-- This won’t block either, and it will be executed after after the other script --> <script src=“script.js” defer></script> <!-- Mind-blowing content here --> … </body> </html> Tuesday, May 1, 12
the script asynchronously, and execute it whenever the loading is done, regardless of source order. <!DOCTYPE html> <html> <head> <!-- This script won’t block and will be executed as soon as it finishes loading --> <script src=“jquery.min.js” async></script> </head> <body> <h1>Welcome to my super-awesome page!</h1> <!-- This won’t block either, and it will be executed when it loads, too --> <script src=“script.js” async></script> <!-- Mind-blowing content here --> … </body> </html> Tuesday, May 1, 12
and works everywhere. But it also means that you have to gang up all of your Javascript elements at the end of the page. And each script will block the ones that follow it. Tuesday, May 1, 12
you’re loading a single library. But this doesn’t really scale if you’re loading a lot of other Javascript. You may want to consider a script loader in that case. Tuesday, May 1, 12
also add to the execution times and overall weight of your pages. And they can have quirky behaviors. Also note that most of these will cause other scripts to load after the DOM ready event. So use a library that handles this case (e.g., jQuery). Tuesday, May 1, 12
and provides some control over script execution order. And they can be mixed with other techniques, such as script loaders. This method doesn’t provide any clear way to fire callbacks. And older browsers don’t support it, or have inconsistent support. But to be clear: async and defer are the future! Tuesday, May 1, 12
other things to consider: • Less is always better; do you really need jQuery? • Cache everything you can; avoid HTTP requests whenever possible • Avoid touching the DOM • Learn more about Javascript! And check out other optimizations, too. Tuesday, May 1, 12
Steve Souders! stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/ Check out the typefaces • Chunk theleagueofmovabletype.com/chunk • Pictos pictos.cc •Veneer Extras yellowdesignstudio.com Tuesday, May 1, 12