We rely on an ever-increasing number of third-party widgets when we build our pages. Some make our pages more feature-rich or social, others generate revenue, and still others let us analyze our traffic or otherwise help us behind the scenes. We just can't live without our widgets!

But they're a double-edged sword. The more widgets you load, the more they can delay your page loading - especially if your page requires JavaScript or AJAX to execute quickly on window.onload or $(document).ready. It can be an excruciatingly bad user experience if your page freezes for several seconds while waiting in line behind some slow-loading ad or widget.

For me, this came to a head while I was developing the TVGrid project. Out of that frustration came LateLoad: a JavaScript class you can use to force third party widgets to delay loading their scripts until your page is ready for them to load.

How to Use LateLoad

The first step is to download the current version of lateload.zip and extract the script file. It needs to be placed in the document before any of the snippets that you want to late-load.

<script type='text/javascript' src='/path/to/lateload.version.js'></script>

LateLoad works with widgets that load external JavaScript files, which insert code and/or more HTML elements into your page. So the next step to using LateLoad is to examine the widget's snippet that you had to add to your page. For example, this widget puts a few social buttons on your page, plus a hit counter, but takes so long to initialize itself that we want to delay the script from loading until window.onload fires:

<!-- CoolExample Button BEGIN --> <div class='CoolExample CoolExample_default_style '> <a class='FriendFace_button'> <a class='Twitter_button'> <a class='Digg_button'> <a class='CoolExample_counter'> </div> <script type='text/javascript' src='http://stuff.CoolExample.com/js?id=9s9djr32'></script>

The <div> doesn't pose any problems for us - it gets parsed quickly. But we want to delay loading the <script> tag that comes after it. All we need to do is replace that line with something like this:

<!-- CoolExample Button BEGIN --> <div class='CoolExample CoolExample_default_style '> <a class='FriendFace_button'> <a class='Twitter_button'> <a class='Digg_button'> <a class='CoolExample_counter'> </div> <script type='text/javascript'> lateLoad.later ('http://stuff.CoolExample.com/js?id=9s9djr32'); </script>

This is the simplest way to call LateLoad. This will wait until the window.onload event fires, and then load the offsite script as a new <script> element at the end of the document.

Try it out

Demo page (jQuery loaded)

Demo page (not using jQuery)

Downloads

The lateload zip file contains both source & minified versions of the lateload .js file, plus the demo pages above. You can check out the project on GitHub.

Release dateVersionFilename
03-may-2012 Beta 1 lateload.beta.1.zip

The API

LateLoad has two methods: later and now. You'll always call later; depending on how you call later, you'll also call now.

lateLoad.later ( url, { when: how-to-delay, where: where-to-insert })

This method registers an external script for loading some time in the future. You'll normally replace a <script src=...> tag in your widget's snippet with a call to this method inside a simple <script> tag.
Required parameters
url
string
The url of the offsite script to load. This is the src= value in the <script> tag in the widget's snippet.
{Optional named parameters}
when:
string or integer
When to load the script:
ValueMeaning
'onLoad'
(default)
This script will be loaded when the window.onload event fires.
'onDocumentReady' If you're using jQuery, this script will be loaded when $(document).ready fires. NOTE: window.onload fires after $(document).ready, so even if you're using jQuery you might still want to go with the default of "onLoad".
custom name If you specify a custom name for the lateloading event here, the script won't get lateloaded until you call lateLoad.now. Use a name that identifies which widget you're lateloading. (Ex.: 'CoolExample')
where:
string or object
Where in the document to load the script:
ValueMeaning
'last'
(default)
The script is loaded as the last element in the document. This should be fine for any widget whose script doesn't care where it gets loaded.
'here' The script is loaded into the script element that lateLoad.later was called from. NOTE: This will delete that element's current contents, so make sure the call to lateLoad.later is in its own <script> tag.
'#elementId' The part after the # is taken as an element's ID. The script is loaded after this element.
jQuery object The result of a jQuery $(...) call. The script is loaded after the first element in the resultset.
DOM object A raw DOM object, as you would get after calling document.getElementById. The script is loaded after this element.

lateLoad.now (name)

This method loads a script that was named in a call to lateLoad.later, or loads all remaining named scripts that haven't been loaded yet.
Optional parameters
name
string
The custom name that identifies which script to load now.
ValueMeaning
''
(default)
This loads all the remaining scripts that were given a name in lateLoad.later that haven't been loaded in yet.
custom name A custom name that you specified when you called lateload.later.

Compatibility

So far I've been testing LateLoad with a few widgets, and most of them work just fine. Please report your experiences with LateLoad in the comments below, and I'll update this list.

CAUTION: Save your widget's snippets before you perform any surgery on them!

WidgetWorks?Notes
AddThis YES Snippet consists of a <div> followed by a <script> with "src=". The default call to lateLoad.later works fine.
Google Analytics YES Snippet consists of a <script> which sets some variables, followed by a <script> with "src=". Replace the second <script> with a default call to lateLoad.later.
Disqus YES The Disqus widget is a heavyweight widget which loads several scripts and css files, so your page will really benefit from lateloading it. In the "DON'T EDIT BELOW THIS LINE" section, change the anonymous function call in ( ) to a default call to lateLoad.later:

lateLoad.later ('http://' + disqus_shortname + '.disqus.com/embed.js');

Google Adsense No An Adsense ad consists of a <script> where some variables are set, followed by a <script> that loads the remote .js file. But so far I haven't been able to get the ad to show up.
Amazon Affiliate ad No An Amazon display ad is implemented with an <iframe>. LateLoad can't help with this type of widget.

Prior art, or: GMTA!

While researching this, I found a couple good references to similar techniques for late-loading scripts.

  • Steve Souders (of course!) details several methods in his Even Faster Web Sites: Performance Best Practices for Web Developers. The LateLoad library basically implements the "script DOM element" technique, albeit with a lot of flexibility.
  • H/T to Emil Stenström for his excellent survey of late-loading techniques. I'm also stealing his attachEvent/addEventListener technique.
  • The interwebs are such a big place, I'm sure there's other good prior art out there. Please give their authors a shoutout in the comments.