Smarter Script Loading with LABjs
We all know that asynchronous resource loading is the key to preventing unwanted and unnecessary blocking within the browser. There are many scripts/libraries available to help with async script loading but the ones that succeed are simple, compact, and reliable. Those words describe Kyle Simpson's LABjs, a lightweight utility for loading your scripts without blocking.
Download LABjs
You can download LABjs at the LABjs website or via GitHub.
Traditional Script Inclusion
Traditional script inclusion blocks subsequent resources from loading. The following is traditional, blocking script inclusion:
<script src="mootools-1.3.js"></script> <script src="lightface/Source/LightFace.js"></script> <script src="lightface/Source/LightFace.Request.js"></script> <script src="lightface/Source/LightFace.Static.js"></script> <script src="Color.js"></script>
Wait...wait...wait. What a waste of time. Other pieces of the page don't rely on these scripts, so why should users have to wait for these scripts to load before other resources load? LABjs fixes this mess.
LABjs Usage
LABjs itself needs to be included within the page via traditional SCRIPT tag:
<script src="LAB.js"></script>
The $LAB
variable is LABjs' handle. You can load scripts using the script method:
$LAB.script('mootools-1.3.js');
The wait
method allows you to prevent script execution (not loading) before executing subsequent scripts in the chain:
$LAB .script('mootools-1.3.js').wait() .script('mootools-dependent-script.js');
Using wait
is a great way to manage dependencies. For example, you cannot load MooTools More before MooTools Core, right? Even though you direct Core to load first, More may load before Core. That will cause many, many errors. You can use wait
to prevent that problem:
$LAB .script('mootools-1.3.js').wait() .script('mootools-1.3-more.js');
The wait
method also acts as a callback for when scripts are done loading:
$LAB .script('mootools-1.3.js').wait() .script('mootools-1.3-more.js').wait(function() { // Now that the Fx.Accordion is available.... var accordion = new Fx.Accordion(/* ... */); });
To complete the example I started this post with:
$LAB .script('mootools-1.3.js').wait() .script('lightface/Source/LightFace.js').wait() .script('lightface/Source/LightFace.Request.js') .script('lightface/Source/LightFace.Static.js').wait(function() { var modal = new LightFace.Request(/* */); }) .script('Color.js')
Using LABjs to load scripts is as simple as that!
LABjs Options
LABjs also provides a bevy of options to customize script loading to your personal needs. Options may be set via the setOptions method:
$LAB.setOptions({ AlwaysPreserveOrder:true });
A few of the options include:
AlwaysPreserveOrder
: Implicitly calls wait() after each scriptUsePreloading
: Allows LABjs to try other loading tricks (trick information here)BasePath
: Sets a base path for all scripts
Many other options are available. You can get more information about LABjs options by reading the documentation.
LABjs + Async FTW
LABjs is an awesome, awesome little utility: compact, easy to use, and reliable. Twitter must agree with me because they are using LABjs. Big props to Kyle for his outstanding work. Be sure to give LABjs a try; low risk, high reward.
WoW.. what a great resource David! Thanks a lot!!
Here is mine just for clicking events https://github.com/Pozo/bismuth
Looking good, but wouldn’t it also work just adding the script-tag to the end of the html?
That way the page would be displayed first, since the Javascript isn’t needed at that time at all..
An hour ago I stumbled upon head.js and now I see a similar LAB.js. I have to compare the options available, because to be honest i was quite exited when I saw those of head.js.
there is another similar require.js, LAB.js can not judge whether a script has been loaded already
Hi david,
Excellent information….
In webkit based browsers there is still an iritating javascript loading que hazard. It doesn’t matter in what order you specify your scripts – even in the header – it will load them as it pleases. Will this LABjs help me in forcing those browsers to “behave”?
I’m not aware of the details of that WebKit issue. Is there documentation somewhere I can look at?
Very popular at delicious.com:
http://headjs.com/
I’m not a programmer, but the facts and features sound good.
@ikon @david —
what i believe you’re referring to is that in Webkit (and indeed, also IE), if you dynamically add a bunch of script elements to a page, they will execute in “as soon as possible” order, not maintaining their insertion execution order. am i right?
if so, you’ve hit on *exactly* why LABjs exists, to smooth out that problem. LABjs goes to great lengths to normalize loading and execution order behavior among the browsers.
the .wait() in a chain will tell LABjs to make sure that scripts before the
.wait()
*execute* before scripts after the.wait()
. All will still be loaded in parallel, but LABjs uses various tricks to “preload” them without execution, so that it can execute them in the order you specify by using.wait()
.side note: you can take a shortcut and just say you want *all* your scripts to execute in order (instead of adding a
.wait()
after every single one yourself), by setting the optionAlwaysPreserveOrder
totrue
, like this:I don’t see how different lab.js logic is different from for example
If you wrap the asset calls in a chain you get the desired order don’t you?
@Diego-
What LABjs does that may not be apparent is that it loads all scripts in the chain in parallel, but executes them in serial order. Just looping over a simple chain of loading calls will result in serial loading rather than parallel, which may be much slower.
Thanks for the reply, I am sure i will give your script a try.
Excellent!
my preferred script loader is JSLoad. you should check it out.. the biggest difference with LABjs and other loader out there is you can define dependencies from the start, without having to do all those long chaining in all your pages.
with LABjs you have to write this in every part of your application that needs a lightbox.
with JSLoad you can instead create a central dependency config that can be used everywhere. so you do something like this instead.
and on every page that needs the lightbox, u simply run this:
without having to rewrite all those long script chains.
@Rizky – LABjs’ API, the .script() function, accepts an array. You could extremely easily predefine your list of scripts in array, and re-use that, without a big long chain. I’m not sure I see how that’s a weakness of LABjs compared to your loader.
I have a PHP session variable named $_SESSION[‘token’] and assigning this to a javascript variable js_token. This is done in the php page itself within script tags. Now I need to access this variable from a js file that I have loaded via labjs. The problem is that labjs loads all the js files at the top of the header and the variable assigning script is placed after all the js files.
This creates a problem as I cannot access the js_token variable.
How can I fix this issue?
Does labjs has any use in today’s JS world? can you do this using promise rather?