Details on dynamic loading of LABJS files on demand

  • 2020-06-07 03:59:27
  • OfStack

LABjs is a small JavaScript tool for loading JavaScript files as needed. By using this tool, you can improve page performance, avoid loading unnecessary JavaScript files, realize dynamic parallel loading of script files, and manage the execution order of loading script files.

A simple example


$LAB
.script("script1.js", "script2.js", "script3.js")
.block(function(){
  // wait for all to load, then do something
  script1Func();
  script2Func();
  script3Func();
});

Here are some examples of LABJS:
Example 1:


$LAB
  .script("script1.js")
  .script("script2.js")
  .script("script3.js")
  .wait(function(){ //  Wait for all script After loading, execute the code block 
    script1Func();
    script2Func();
    script3Func();
  });

Example 2:


$LAB 
  .script({ src: "script1.js", type: "text/javascript" })
  .script("script2.js")
  .script("script3.js")
  .wait(function(){ //  Wait for all script After loading, execute the code block 
    script1Func();
    script2Func();
    script3Func();
  });

Example 3:


$LAB
  .script("script1.js", "script2.js", "script3.js")
  .wait(function(){ //  Wait for all script After loading, execute the code block 
    script1Func();
    script2Func();
    script3Func();
  });

Example 4:


$LAB
  .script( [ "script1.js", "script2.js" ], "script3.js")
  .wait(function(){ //  Wait for all script After loading, execute the code block 
    script1Func();
    script2Func();
    script3Func();
  });

Example 5:


$LAB
  .script("script1.js").wait() //  empty wait() Just make sure script1 Is executed before any other code 
  .script("script2.js") // script2  and  script3  Depends on the  script1
  .script("script3.js").wait() //  but script2  and  script3  Not dependent on each other , You can download it in parallel 
  .script("script4.js") // script4  Depends on the  script1, script2  and  script3
  .wait(function(){script4Func();});

Example 6:


$LAB
  .script("script1.js") // script1, script2, and script3  There are no dependencies between ,
  .script("script2.js") //  So you can do it in any order 
  .script("script3.js")
  .wait(function(){ //  If you need , You can certainly do it here javascript function 
    alert("Scripts 1-3 are loaded!");
  })
  .script("script4.js") //  Depends on the  script1, script2  and  script3
  .wait(function(){script4Func();});

Example 7:


$LAB
  .setOptions({AlwaysPreserveOrder:true}) //  Set the wait between each script 
  .script("script1.js") // script1, script2, script3, script4  Depend on each other 
  .script("script2.js") //  And download in parallel after the sequential execution 
  .script("script3.js")
  .script("script4.js")
  .wait(function(){script4Func();});

Example 8:


$LAB
  .script(function(){
    // `_is_IE` The value of the ie for true , non ie for false
    if (_is_IE) {
      return "ie.js"; //  If it is ie Is this js Will be loaded 
    }
    else {
      return null; // If it is not ie This code will be skipped 
    }
  })
  .script("script1.js")
  .wait();

LABjs loading mode

The dynamic load script file in LABjs refers to the various ways to load the external js during the execution of the js script (mainly different from the html page) < script > Statically loaded script for tags)

There are many ways to dynamically load scripts. There are both advantages and disadvantages. If you are interested, please refer to the reference link at the end of this article.

Three techniques are used in LABjs, namely Script Element, XHR Injection and Cache Trick

First of all, a brief introduction to the three loading methods, and then analyze the LABjs source code implementation in the face of the three ways of use scenarios

Script Element (LABjs adopts loading mode by default)

The most common method of dynamic script loading has many advantages, including: 1. Easy to implement; 2. Cross-domain; 3

Opera/Firefox (older version) : The order in which the script is executed is 1 in the order in which the nodes are inserted into the page

IE/Safari/Chrome: Execution order cannot be guaranteed

Note:

With the new version of Firefox, the order in which scripts are executed is different from the order in which pages are inserted, but the order can be guaranteed by setting the script tag's async property to false

In older versions of Chrome, the order in which scripts are executed is different from the order in which pages are inserted, but the order can be guaranteed by setting the async property of the script tag to false

XHR Injection
Request to load the script file via ajax and then execute it by:
eval: Common way
XHR injection: Create 1 script element and inject the contents of the script file that you want to load
Main limitation: Cannot cross domain
Cache Trick (strongly browser dependent feature implementation, not recommended)
When you set the type attribute of the script element to a value unknown to the browser, such as "text/cache", "text/casper", "text/hellworld", etc., the behavior of different browsers is as follows:
IE Safari/Chrome (old version) : script loading as usual, but you don't perform, assuming that the browser didn't disable caching, after loading the script will be the browser cache, when needed, just need to create a script labels, set to the correct value type, src file to request before url can (read from the cache files)
Opera/Firefox: not loaded
Remark:
It is strongly dependent on the browser's feature implementation and may fail as the browser's feature implementation changes. It is not recommended
The new version of the chrome browser sets type for the script element to be non-" text/javascript "and does not load script files.

LABjs's judgment on script load adoption

Ignoring technical details, 1 section of pseudo-code is used to describe the implementation in LABjs, which is roughly as follows:
First, determine whether to preload the requested script (the judgment condition of whether to preload is seen in the pseudocode comment);
If preloading is done, then determine whether the browser supports true preloading. Preloading if true preloading is supported; If no, determine whether the requested script is in the same field with the current page. Truthfully, XHR Injection is used. If no, Cache Trick is used.
If no preload is performed, determine whether the browser support supports the async attribute of the script element (see the pseudocode comment). If so, set the async attribute and request the script file. If not, load the script file directly through the script element;


if(ifPreloadScript){  // When the requested script file is preloaded: 1 , which requires pre-loading  2 Browser supports pre-loading 
  if(supportRealPreloading){  // If true preloading is supported 
    if(supportPreloadPropNatively){  // Support through Settings script Of the label preload Property, implementation script Preload, as well as separate load and execution 
                    //Nicholas C. Zakas Great god's good wishes, not yet supported by the browser: /blog/2011/02/14/separating-javascript-download-and-execution/
      script.onpreload = callback;
      script.newPreload = true;
      script.src = targetUrl;
    }else{
      script.onreadystatechange = callback;  // That is to say IE The browser, assuming specified script Elements of the src Properties, IE The browser will load immediately 
      script.src = targetUrl;  // Even if the script The element is not inserted into the page, callback Is a pre-loaded callback 
    }
  }
  else if(inSameDomain){  // Non-cross-domain, adopt XHR Injection : The requested script is on the same page as the current page 1 A domain 
    xhr = new XMLHttpRequest();  // Since the last judgement has been made IE Ruthlessly cast out of this conditional branch, so use boldly  new XMLHttpRequest() ! 
    xhr.onreadystatechange = callback;
    xhr.open("GET",targetUrl);
    xhr.send();
  }
  else{  // The most helpless afterthought, Cache Trick The new chromei No longer supported 
    script.onload = callback;
    script.type = 'text/cache';  
    script.src = targetUrl;
  }
}else{
  if(canContrlExecutionOrderByAsync){  // If you can pass script Elements of the async Property to force parallel loaded scripts to execute sequentially 
                    //kyle Great efforts have been made to advance the proposal html5 The group accepted and put the draft: /Dynamic_Script_Execution_Order#My_Solution
    script.onload = callback;
    script.async = false;  // will script Elements of the async Set to false Can be guaranteed script The order of execution is maintained in the order of requests 1 to 
    script.src = targetUrl;
  }
  else{
    script.onload = callback;
    script.src = targetUrl;  
  }
}

In fact, when you create an img node on a page and point its src to a script file, it will also preload the file in some browsers. Did the authors of LABjs not think of this point?


Related articles: