Load only the jQuery plugins you need, when you need them

jQueryHere’s some jQuery love for you front-end types. I have certainly been enjoying using jQuery a lot lately. So damn efficient and easy to use. An active community means there are lots of handy plug-in libraries out there to take care of your tabs, carousels and fadey bits… (If you’re a HTML/CSS person and you don’t know what all this jQuery stuff is about, have a look at these easy jQuery Tutorials for Designers.)

Once you start getting a few such libraries going on a site, you can end up with a whole pile of script includes in your header for minor user interface enhancements here and there. This can be a hassle to deploy over various page templates/master pages/etc, particularly if you work with large sites. More importantly, you want to minimise requests to the server if they’re not necessary – it’s been shown that reducing HTTP requests can reduce response times and improve server performance.

There are various ways you can reduce HTTP requests from the front-end (like using CSS sprites to reduce image requests, aggregating CSS and JS files), but the tip I want to share is to not include multiple javascript libraries (eg. jQuery plug-ins) on your pages but having your main JavaScript file load the relevant libraries on demand, as the need arises.

JQuery has a handy method for dynamically loading script files: $.getScript()

But you don’t want to load all libraries on $(document).ready (thus when each page loads), instead you only want a plug-in to load when it’s needed. You can do this by testing for the existence of the relevant element(s) first. You can’t do this (as I found when I looked at Firebug’s console) by saying:

if ($(".tabs")) {
	$.getScript(URL, callback function)
}

This will work in other helper libraries like MooTools (as it’s just short form for document.getElementById), but jQuery will return an array of all matched elements, so even if that array is empty it will never return false. This is actually a good feature of jQuery as you don’t have to test for the existence of anything before applying behaviours.

There’s an easy way to get around this (which wasn’t obvious to me right away). Make sure the array length is greater than zero, of course:

if($(".tabs").length > 0) {
	$.getScript(URL, callback function)
}

So a more complete code snippet would look like:

$(document).ready(function(){
	if($(".tabs").length > 0) {
		$.getScript("/scripts/jQuery.idTabs.js", function(){
			$(".tabs").idTabs();
		});
	}
});

Basically, if you include that snippet in your main JS file, then whenever you have an element with given the class “tabs”, then it will load idTabs.js from the location specified and then initialise Sean’s neat script, and you’ll have yourself nice easy tab behaviour.

Thanks to my co-worker buddy Nick at the Valley for introducing me to the $.getScript feature in jQuery.

Update 23/06/08:

It seems in Firefox 3 and Safari Webkit, objects loaded via $.getScript() aren’t instantly available when called via the callback function. Adding a setTimeout of as little as 100ms seems to get around this like so:

$(document).ready(function(){
	if($(".tabs").length > 0) {
		$.getScript("/scripts/jQuery.idTabs.js", function(){
			setTimeout(function(){
				$(".tabs").idTabs();
			}, 100);
		});
	}
});

5 comments

  1. You really saved my day.
    Everytime you try to call a function to an element that does not exist with Query, Firebug reports a “F is not defined” error. Using your function in a slightly different way, i can avoid this error. Many thanks for sharing!

  2. Great, glad it was helpful for somebody. :)
    Thanks for stopping by.

  3. Hiren Mansuriya
    January 22, 2010
    11:48 am

    Thanks man.. It is really helpful…

  4. I wanted to solve two problems: the 200ms might still not be enough depending of the plugin, and I wanted to avoid to force visitors to wait 200ms if the function is already available

    Instead of putting the setTimeout in the callback, I put it on a separate function that contains the init code for the plugin

    http://free.of.charge.and.unasked.eu/lazy_loading_a_jquery_plugin

  5. Yeah that sounds slightly better, though I hope the whole problem has a more graceful solution than just putting a delay on dependent functions.

    Thanks for that workaround (though your link doesn’t seem to work for me).