• This repository has been archived on 31/Dec/2022
  • Stars
    star
    2,277
  • Rank 19,775 (Top 0.4 %)
  • Language
    HTML
  • Created over 14 years ago
  • Updated almost 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Loading And Blocking JavaScript: On-demand parallel loader for JavaScript with execution order dependencies

IMPORTANT: This project is undergoing a complete 3.0 rewrite. Please follow the progress.

LABjs (Loading And Blocking JavaScript)

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="http://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("http://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.

Build Process

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.

Configuration

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) locations
  • AlwaysPreserveOrder: 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 order
  • AllowDuplicates: 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 URL
  • BasePath: {string} (default ""): a path string to prepend to every script request's URL

Protocol-relative URLs

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 "http://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".

New in v2.0

  • AllowDuplicates now actually works across chains. This is very important for those who want to use multiple/nested $LAB chains as part of a shared-dependency loading mechanism.
  • Chains are now fully resumable, meaning you can save the return value from the last call to a chained function, and then use that saved value later as the starting point to resume the chain from where it left off.
  • Queueing is now built-in, with queueScript, queueWait and runQueue -- this important for those who want to build up the chain across multiple files or inline <script> elements (like in the CMS case), but want to defer starting the loading of the code starting until later (usually at the bottom of the page).
  • LABjs now supports noConflict (for rolling back to a previous version/copy of $LAB on the page) and sandbox (for creating a new pristine sandboxed copy of the current $LAB)
  • LABjs now relies on feature-testing for async=false and implicit/explicit "true preloading" (currently only IE, but in the spec process). Ugly/hacky "cache preloading" is now only used for "older webkit" (before March 2011 nightlies, etc), and even then, only for remote files.
  • For XHR preloading (only used in "older webkit" for local files, by default), to support better debugability, "// @sourceURL=..." is appended to the end of the code, to map the XHR/injected code to a real file name. Currently, browsers only support this for eval() (not script injection, like LABjs uses). It is hoped that browsers will soon support this annotation for their developer-tools.
  • Speaking of debugging, LABjs now supports a DEBUG mode (only if you use the source file, or if you use the LABjs-debug.min.js production file) and enable the "Debug" config option, which captures all the inner workings (and any errors in .wait() calls) to the browser's console.log, if present.
  • LABjs now supports a "CacheBust" config option, which will attempt to make sure all loaded scripts are forcibly loaded new on each page refresh, by auto-appending a random number parameter to each URL. This is really only practical/advised for DEV environments, where you want to ensure that the code reloads every time. Doing so in production would be really bad for user performance.*
  • As part of LABjs' rewrite, the code style is now significantly improved in readability (most "minification" hacks have been removed), and it's also using more memory-savvy code, such as far fewer closures. As a result, LABjs should run leaner and faster, if only by a little bit. The goal is to get LABjs out of the way so your scripts load and run as fast as possible.
  • "AppendTo", "UsePreloading", and "UseCachePreloading" options were removed as they are no longer useful. This is the only backwards-incompatible change (no actual API changes, just config), and the change should just cause older usage code to continue to operate as normal while ignoring the no longer supported options. Still, test your code carefully if you've been using either of those 3 config options before.

More Repositories

1

You-Dont-Know-JS

A book series on JavaScript. @YDKJS on twitter.
177,328
star
2

Functional-Light-JS

Pragmatic, balanced FP in JavaScript. @FLJSBook on twitter.
JavaScript
16,518
star
3

asynquence

Asynchronous flow control (promises, generators, observables, CSP, etc)
JavaScript
1,740
star
4

CAF

Cancelable Async Flows (CAF)
JavaScript
1,327
star
5

monio

The most powerful IO monad implementation in JS, possibly in any language!
JavaScript
1,041
star
6

TNG-Hooks

Provides React-inspired 'hooks' like useState(..) for stand-alone functions
JavaScript
1,011
star
7

native-promise-only

A polyfill for native ES6 Promises as close as possible (no extensions) to the strict spec definitions.
JavaScript
725
star
8

A-Tale-Of-Three-Lists

Comparing various async patterns for a single demo
JavaScript
650
star
9

fasy

FP iterators that are both eager and asynchronous
JavaScript
544
star
10

FPO

FP library for JavaScript. Supports named-argument style methods.
JavaScript
448
star
11

youperiod.app

YouPeriod.app -- the privacy-first period tracking app
JavaScript
443
star
12

JSON.minify

Simple minifier for JSON to remove comments and whitespace
405
star
13

TypL

The Type Linter for JS
JavaScript
365
star
14

h5ive-DEPRECATED

**DEPRECATED** A collection of thin facade APIs wrapped around HTML5 JavaScript features.
JavaScript
324
star
15

eslint-plugin-proper-arrows

ESLint rules to ensure proper arrow function definitions
JavaScript
305
star
16

foi-lang

Foi: a different kind of functional programming language
JavaScript
302
star
17

grips

Simple-logic templates
JavaScript
287
star
18

moduloze

Convert CommonJS (CJS) modules to UMD and ESM formats
JavaScript
205
star
19

ES-Feature-Tests

Feature Tests for JavaScript
JavaScript
199
star
20

let-er

DEPRECATED: Transpile non-ES6 let-blocks into ES6 (or ES3)
JavaScript
192
star
21

Incomplete-JS

"The Incomplete Guide to JavaScript" (book). @IncompleteJS on twitter.
190
star
22

revocable-queue

Specialized async queue data structure, supports revocation of values
JavaScript
176
star
23

deePool

highly-efficient pool for JavaScript objects
JavaScript
115
star
24

getify.github.io

JavaScript
109
star
25

concrete-syntax-tree

Defining a standard JavaScript CST (concrete syntax tree) to complement ASTs
107
star
26

eslint-plugin-proper-ternary

ESLint rules to ensure proper usage of ternary/conditional expressions
JavaScript
95
star
27

cloud-sweeper

A casual game built for the web.
JavaScript
93
star
28

BikechainJS

JavaScript VM engine (powered by V8); server-side environment modules; server-side synchronous web app controllers
C++
81
star
29

wepuzzleit

Demo PoC game for various advanced HTML5 js APIs
JavaScript
78
star
30

workshop-periodic-table

65
star
31

elasi

EL/ASI: Encrypt Locally, Account Secure Interchange
JavaScript
60
star
32

remote-csp-channel

Remote bridge for CSP channels
JavaScript
55
star
33

ScanTree

Scan a JS file tree to build an ordered and grouped dependency listing
JavaScript
51
star
34

dwordly-game

A game where words dwindle down to the shortest possible
JavaScript
42
star
35

stable-timers

timers with less race conditions
JavaScript
38
star
36

emdash

Simple blogging with node/iojs + GitHub.
36
star
37

domio

DOM and Event helpers for Monio
JavaScript
30
star
38

eslint-plugin-no-optional-call

ESLint plugin to disallow the optional-call operator
JavaScript
30
star
39

eslint-plugin-arrow-require-this

DEPRECATED: ESLint rule to require arrow functions to reference the 'this' keyword
JavaScript
28
star
40

import-remap

Rewrite ES module import specifiers using an import-map.
JavaScript
25
star
41

gum-try-hd

Try to enforce HD (16:9) camera aspect ratio for web-video calls
JavaScript
25
star
42

Mock-DOM-Resources

A mock of (parts of) the DOM API to simulate resource preloading and loading
JavaScript
25
star
43

make-a-game

some project files for a tutorial on making a simple web game
JavaScript
24
star
44

mpAjax

framework plugin for handling multi-part Ajax responses
JavaScript
23
star
45

asyncGate.js

DEPRECATED. asynchronous gate for javascript
JavaScript
21
star
46

tic-tac-toe-workshop

Workshop files for building tic-tac-toe in JS and <canvas>
21
star
47

esre

esre: fully configurable JS code formatting
20
star
48

workshop-chess-diagonals

17
star
49

featuretests.io

JavaScript Feature Tests... as a service
JavaScript
16
star
50

FoilScript

FoilScript: a new dialect of JS that fixes the sucky parts but still looks and feels like JS
16
star
51

literalizer

Specialized heuristic lexer for JS to identify complex literals
JavaScript
15
star
52

normalize-selector

Normalize CSS selectors
JavaScript
14
star
53

DOMEventBridge

Bridge DOM events to a JS event hub (for pubsub)
JavaScript
14
star
54

pong-around-workshop

Workshop files for building a pong-variant game in JS and <canvas>
12
star
55

shortie.me

Proof-of-concept demo for server-side JavaScript driven "middle-end" architecture
JavaScript
11
star
56

workshop-wordy-unscrambler

10
star
57

middleend-boilerplate

Boilerplate Starting Point for Middle-end Web Architecture
JavaScript
8
star
58

workshop-knights-dialer

7
star
59

demo-app-weatheround

JavaScript
7
star
60

the-economy-of-keystrokes-slides

Slides code built for "The Economy of Keystrokes" talk
JavaScript
6
star
61

santa-connect-app

Santa Connect: keeping track of your kids' nice/naughty status
JavaScript
5
star
62

nyc-bug-demo

bug demo for NYC code coverage tool
JavaScript
5
star
63

unnamed

unnamed (for now). nothing to see here. ;-)
JavaScript
2
star
64

my-lifesheets

CSS
1
star
65

breakthewebforward.com

JavaScript
1
star