LABjs is a dynamic script loader intended to replace the use of the ugly, non-performant <script> tag with a flexible and performance-optimized alternative API.
The defining characteristic of LABjs is the ability to load all JavaScript files in parallel, as fast as the browser will allow, but giving you the option to ensure proper execution order if you have dependencies between files.
For instance, the following "<script>
tag soup":
<script src="https://remote.tld/jquery.js"></script>
<script src="local/plugin1.jquery.js"></script>
<script src="local/plugin2.jquery.js"></script>
<script src="local/init.js"></script>
<script>
initMyPage();
</script>
With LABjs becomes:
<script src="LAB.js"></script>
<script>
$LAB
.script("https://remote.tld/jquery.js").wait()
.script("/local/plugin1.jquery.js")
.script("/local/plugin2.jquery.js").wait()
.script("/local/init.js").wait(function(){
initMyPage();
});
</script>
The differences between the two snippets is that with regular <script> tags, you cannot control their loading and executing behavior reliably cross-browser. Some new browsers will load them in parallel but execute them serially, delaying execution of a smaller (quicker loading) script in the pessimistic assumption of dependency on previous scripts. Older browsers will load and execute them one-at-a-time, completely losing any parallel loading speed optimizations and slowing the whole process drastically.
All browsers will, however, block other page resources (like stylesheets, images, etc) while these scripts are loading, which causes the rest of the page's content loading to appear much more sluggish to the user.
LABjs by contrast will load ALL the scripts in parallel, and will execute them as soon as possible, unless you express an execution order dependency in the chain by inserting .wait(). In addition, you can "couple" inline script logic to execute in the proper order in your chain as desired by passing a function to .wait(...).
It's important to realize that explicitly, separate $LAB chains operate completely independently, meaning there will be no explicit waiting for execution order between them.
NOTE: JavaScript execution is always still a single-threaded, first-come-first-served environment. Also, some browsers use internal loading queues which create implicit "blocking" on script execution between separate chains. Also, the 'AllowDuplicates:false' config option will de-duplicate across chains, meaning chain B can be made to implicitly "wait" on chain A if chain B references a same script URL as chain A, and that script is still downloading.
There is no "official" build process or script. There is however "BUILD.md" which lists the steps that I take to prepare the LAB.min.js and LAB-debug.min.js files.
There are a number of configuration options which can be specified either globally (for all $LAB chains on the page) or per chain.
For instance:
$LAB.setGlobalDefaults({AlwaysPreserveOrder:true});
would tell all $LAB chains to insert an implicit .wait() call in between each .script() call. The behavior is identical to if you just put the .wait() call in yourself.
$LAB.setOptions({AlwaysPreserveOrder:true}).script(...)...
would tell just this particular $LAB chain to do the same.
The configuration options available are:
UseLocalXHR
: true/false (default true): use XHR to preload scripts from local (same-domain) locationsAlwaysPreserveOrder
: true/false (default false): whether to insert an implicit .wait() call after each script load request... if turned on, prevents immediate execution of loaded files and instead executes all scripts in orderAllowDuplicates
: true/false (default true): whether to inspect the current page and $LAB loading cache to see if the same script URL has already been requested and allow (true) or ignore (false) if so. NOTE: in v1.2.0 and before, this didn't work correctly across multiple $LAB chains, but as of v2.0, it works correctly.CacheBust
: true/false (default false): adds a cache-busting parameter (random number) to the end of a script URLBasePath
: {string} (default ""): a path string to prepend to every script request's URL
Browsers have long supported "protocol-relative URLs", which basically means leaving off the "http:" or "https:" portion of a URL (leaving just the "//domain.tld/path/..." part), which causes that URL to be assumed to be the same protocol as the parent page. The benefit is that if you have a page that can be viewed in either HTTP or HTTPS, and your resources can (and need to be) served through either HTTP or HTTPS, respectively, you can simply list your URLs as protocol-relative and the browser will auto-select based on which protocol the page is viewed in.
LABjs now supports specifying such URLs to any script URL setting. NOTE: This is the recommended way to specify URLs for script resources if: a) the page you're serving can be viewed in both HTTP and HTTPS; and b) the script resource you're linking to can be accessed using the exact same domain/path with exception to the protocol.
A common example of such a resource is the CDN locations on the Google Ajax API, where popular frameworks like jQuery and Dojo are hosted. If you are linking to such CDN resources, you are strongly encouraged to change to using protocol-relative URLs, like "//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" instead of "https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" or "https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js".
- Support for the new
<link rel=preload>
capabilities coming soon to modern browsers. - ...