Description

This project is a simple little tool for being able to load javascript files dynamically. It's like many script loaders where the goal is to improve the speed of page load by allowing scripts to load in parallel. The thing it does differently than most others is it allows you to express via the API calls when it is necessary to preserve execution order for dependencies. By default, all scripts will still load in parallel, but execution order will be deferred until the proper time, if necessary.

What most loaders fail to do well (easily) is let you define dependencies simply based on loading order and the API calls. With regular script tags, the browser blocks for you, so you know for instance that jquery.js executes before jquery.ui.js.

Imagine this scenario: 3 scripts that can be executed in parallel (not dependent on each other), and then two more that need to wait for those 3 to load before executing. You can't do that with script tags, and you also can't do that very easily with most of the script loaders/frameworks out there.

Most of them rely on intrusive concepts to do dependency management. For instance, each child script might have to "signal" (callback) that it's done loading, to the parent page or loader. Or the parent script and child scripts have to explicitly declare dependencies using some framework or conventions (comment annotations, etc). Also, some other loader libraries rely on attaching a single load callback handler for EACH script. This makes it awkward or difficult to wait for several to execute as a group, before proceeding, since you as the author have to keep track of what has loaded yourself.

LABjs lets you load pretty much any script file, whether you control it or not, with no intrusion or convention for dependencies, other than the order and blocking that you define. It keeps track of what you've asked for and what has downloaded, and lets you only define a handler once for a group of scripts that will execute together in parallel. The API style (with chaining) makes is very easy to convert a set of script tags in your page into code to load them, without having to worry that race conditions will cause issues for scripts loading in the wrong order if there are explicit dependencies involved.


When/Why to use LABjs?

The question comes up quite often, "why use LABjs instead of just minifying and combining files?" Very simple answer. This is not either-or, it's BOTH. Minify and combine your files when you can -- this generally will create better loading experience for your users, if you reduce the number of HTTP requests the browser and server have to negotiate.

But, you will end up with one or a couple of files, and they will generally be larger file assets which take longer to load. So, use LABjs even to load these combined/minified files. Why? Because LABjs not only makes script downloads parallel to each other, but also to other assets on the page. So, making your script load parallel to page assets will help the overall page load faster, guaranteed. It assists with the concept of progressive-enhancement by loading your page assets as quickly as possible, then decorating them with scripts as soon as they become available.

Also, and this is a very important point, I've almost never seen a site where all site code is self-hosted and loaded by the same server. In the real world, there are generally several cases where files can and should (and sometimes must) be loaded from other locations. These files may be jquery.js hosted from a CDN, or the google-analytics code, or your social sharing widget (addthis, etc), or any number of other types of external script assets which your page needs.

Sometimes these are auxilliary assets (meaning if they load or not, the page will be just fine), but in some cases (jquery.js), it may be critical that such files load as soon as possible but don't block each other or the rest of the page. When you are loading scripts from other locations, LABjs is almost always going to be the best way to do so. Plain and simple, it will make your page load faster and more reliably.

You can read more about LABjs and JavaScript concat'ing in that post on getiblog.


When not to use LABjs

Before I explain when not to use LABjs: LABjs can and should be used on virtually any site. It just shouldn't be used for loading a couple of special file types (they should be loaded manually with regular script tags for now, instead). But everything else on your site can and will benefit from loading with LABjs.

document.write()

Don't use LABjs with scripts that have document.write() in them. At least not yet. document.write() is natively synchronous and thus will break with the asynchronous loading techniques inherent to LABjs. There is an effort underway to create a document.write() replacement that will operate much the same way but will be async safe, called "DomWrite". DomWrite, used in conjunction with LABjs, will allow you to safely load scripts with document.write() in them via LABjs. Stay tuned for more information on this.

Certain frameworks which have unsafe DOM-ready detection

There is one more case where I would recommend, at least for now, not using LABjs (or any other dynamic loading technique) for loading a script asset. There are scripts that do DOM-ready detection, such as jquery.js. Unfortunately, some of these methods for DOM-ready detection are flawed in one specific case -- when the file with the DOM-ready detection loads in a page AFTER the DOM-ready has already happened. They do a bad job of detecting that this is the case, in some browsers, and so wait "forever" thinking they are still waiting for DOM-ready to occur. This means that any code which is queued up waiting for DOM-ready to occur never gets executed.

So, if you load such a script dynamically with LABjs, and you have optimized the rest of your page in such a way that DOM-ready happens before that script gets there, then your page will be left in an uninitialized state because DOM-ready will have passed and will not fire a second time.

If you're interested in the nitty gritty details, read this post on getiblog about DOM-ready detection in frameworks and LABjs.

jQuery 1.3.2 and below suffers from this problem, as do some others. However, a bug was filed with jQuery about this, and a fix has been put in for the upcoming 1.4 release. So, once 1.4 comes out, jQuery will be fine to load with LABjs. But 1.3.2 and below should not be loaded with LABjs because of this race condition between script loading and the actual DOM-ready event.

There's a simple fix to this issue, though. Simply load ONLY the jquery.js (1.3.2 and below) script file (or whatever other script has its own unsafe DOM-ready detection logic in it) manually, using a regular script tag. This will guarantee that its internal DOM-ready detection will occur correctly, since the script tag you load it with will block DOM-ready for it to load first. Once jQuery has registered DOM-ready, all other plugins and blocks of $(document.ready(function(){...}); that queue for the DOM-ready event will work fine, even though you load them with LABjs.

Bottom line: only the few special scripts out there, like libraries, that do their own DOM-ready detection, and don't do so in a dynamically-loaded-after-page-load safe way, will have possible problems if loaded by LABjs, so avoid it only in those rare cases. Simply load those special scripts with a manual script tag like always before. In all other cases, including your plugins which rely on that logic working correctly, LABjs is perfectly safe and good to use!