Implementation and loading of high performance JavaScript

  • 2020-12-09 00:41:10
  • OfStack

The browser handles HTML page rendering and JavaScript script execution in a single process, so it encounters HTML when the browser is rendering < script > The tag executes the code inside the tag first (if it is an external linked file loaded using the src property, download it before executing it), and during this process, page rendering and interaction are blocked.

. There will be blocking, but there are a few ways to reduce the performance impact of JavaScript.

1. Location of script tag

when < script > Appear in the < head > For example:


<head>
  <script type="text/javascript" src="js1.js"></script>
  <script type="text/javascript" src="js2.js"></script>
  <script type="text/javascript" src="js3.js"></script>
</head>

When loading multiple js files, the browser blocks the page rendering by downloading and executing js code first, resulting in a white screen < body > No page content is rendered before the tag), no preview, no interaction, poor user experience.

Note:

Modern browsers support parallel download of resources, only limited to < script > Downloading external resources does not block others < script > Tag, but can block downloads of other resources.
Downloading the JavaScript resource is asynchronous, but executing the JavaScript code is still synchronous, again causing a block.
So the < script > The rear to < body > The bottom of the TAB, which ensures that the page is rendered before the script is executed, is one of the more common JavaScript optimizations.

2. Merge multiple script tags

Encountered when the browser parses HTML < script > There is a definite delay due to the execution of the script, as is the case for chains with the src attribute < script > What's more, more HTTP requests will bring more performance overhead, so as to minimize this delay, which is also an optimization method. Multiple js files can be combined to reduce the number of HTTP requests, reduce the number of three handshakes and the redundant HTTP header transmission, and reduce the response time and improve the user experience. There are many solutions and tools for incorporating js on the Web, which I won't cover here.

3. Download JavaScript without blocking

Use the defer and async attributes of the script tag Use the dynamically created script tag to download and execute the JavaScript code Use the XHR object to download the JavaScript code and inject the page

3.1. defer and async attributes using the script tag

The async and defer attributes are used to load the js file asynchronously without blocking other processes in the browser. The difference is that async is automatically executed after loading, while defer needs to wait until the page is loaded. One thing to note is that these two attributes must be in the src attribute < script > Tag (outer chain script) is only valid. The following is demo:


<!DOCTYPE html>
<html>
<head>
  <title>defer example</title>
</head>
<body>
  <script type="text/javascript" src="defer.js" defer></script>
  <script>
    alert("script");
  </script>
  <script>
    window.onload= function(){
      alert("load");
    }
  </script>
  <div class="demo">defer demo</div>
  <div class="demo">defer demo</div>
  <div class="demo">defer demo</div>
  <div class="demo">defer demo</div>
  <div class="demo">defer demo</div>
  <div class="demo">defer demo</div>
  <div class="demo">defer demo</div>
  <div class="demo">defer demo</div>
  <div class="demo">defer demo</div>
  <div class="demo">defer demo</div>
  <div class="demo">defer demo</div>
  <div class="demo">defer demo</div>
</body>
</html>

// defer.js has only alert("defer") under the file; One line of code
The async example is also the same page structure, I won't put the example here, you can poke the link below.
defer example's link stamp here!
async example's link stamp here!

The page structure is one, but not the other

Open defer.html and see in turn: Pop up alert box of "script" = > Page rendering text = > Pop up alert = for "defer" > Pop up the alert box for "load"
Open ES129en. html and see in turn: alert box = pop out "script" > Pop up alert = for "async" > Page rendering text = > Pop up the alert box of "load"

3.2. Download and execute the JavaScript code using the dynamically created script tag


var script = document.createElement("script");
script.type = "text/javascript";
script.src = "file.js";
document.getElementByTagName("head")[0].appendChild(script);

file.js starts the download as soon as the script element is added to the page. The advantage of using this approach is that the download and execution of ES151en.js does not block other processes on the page.

It is obvious from demo that the dynamic loading method can see the text on the page before the alert box pops up, but the normal way can only see the text on the page after the alert box pops up.

We can encapsulate a function that reads the script script across browsers and dynamically creates the script tag:


function loadScript(url,callback){
  var script = document.createElement("script");
  script.type = "text/javascript";
  // Detect the client type 
  if(script.readyState){//IE
    script.onreadystatechange = function(){
      if(script.readyState==="loaded"||script.readyState==="complete"){
        script.onreadystatechange = null;
        callback();
      }
    }
  }else{// Other browsers 
    script.onload = function(){
      callback();
    }  
  }
  
  script.src = url;
  document.getElementsByTagName("head")[0].appendChild(script);
}

This type of dynamic load script is a common non-blocking solution with good compatibility and simplicity.

3.3. Use the XHR object to download the JavaScript code and inject the page

Another way to load a script without blocking is to use the XMLHttpRequest(XHR) object to get the script and inject it into the page.
This technique creates an XHR object, uses it to download the JavaScript file, and finally passes through the common dynamics < script > Element to inject code into the page.


var xhr = new XMLHttpRequest();
xhr.open("get","file.js",true);
xhr.onreadystatechange = function(){
  if(xhr.readyState===4){
    if(xhr.status>=200&&xhr.status<300||xhr.status==304){
      var script = document.createElement("script");
      script.type = "text/javascript";
      script.text = xhr.responseText;
      document.body.appendChild(script);
    }
  }
}

The above code sends GET to request the ES183en.js file. onReadyStateChange detects whether readyState is 4(4 means the request is complete) and whether the HTTP status is valid (200 means a valid response,304 means read cache). After determining that the response is valid, create one dynamically < script > Tag, the content is responseText received by the server.

Advantages and disadvantages of this approach:

Pros: The JavaScript code can be downloaded without immediate execution and is compatible with all major browsers.
Disadvantages: The JavaScript file must be in the same domain as the requested page, in which case the JavaScript file cannot be downloaded from CDN and is not suitable for large Web applications.

4.1 Recommended non-blocking schemes

If a large amount of JavaScript code needs to be added to the page, the function loadScript which we have encapsulated to dynamically read script script before the outer link is removed from the page can be used to load other required scripts, such as:


<script type="text/javascript" src="loader.js"></script>
<script type="text/javascript">
  loadScript("file.js",function(){
    //do something
  });
</script>

So you only have to do it in the first one < script > Downloading the more compact ES216en.js file has a slight impact on the page after < script > It won't make much difference.


Related articles: