Non-blocking JavaScript scripts and extended knowledge

Source: Internet
Author: User

JavaScript tends to block some browser processing processes, such as HTTP requests and interface refresh, which are the most significant performance problems faced by developers. Keeping JavaScript files short and limiting the number of HTTP requests is only the first step in creating responsive web applications. The more functions an application contains, the larger the JavaScript code is required. It is not always a choice to keep the source code short. Although downloading a large JavaScript file generates only one HTTP request, it will lock the browser for a long time. To avoid this situation, you need to gradually add JavaScript to the page, to some extent, it will not block the browser. The secret of a non-blocking script is that after the page is loaded, the JavaScript source code is loaded. Technically speaking, this means that the Code will be downloaded after the window load event is triggered. There are three ways to achieve this effect.

Extension script

HTML 4 defines an extension attribute for the <script> tag: defer. This defer attribute specifies that the script contained in the element does not intend to modify the DOM, so the code can be executed later. The defer attribute is only supported by browsers of Internet Explorer 4 and Firefox 3.5 and later versions. It is not an ideal cross-browser solution. In other browsers, The defer attribute is ignored. <script> labels are processed by default (blocking is caused ). This method is still a useful solution if the browser supports it. Example:

<script type="text/javascript" src="file1.js" defer></script>

A <script> tag with the defer attribute can be placed anywhere in the document. The corresponding JavaScript file will start download when <script> is parsed, but the code will not be executed until the DOM loading is complete. (Before the onload event handle is called ). When a defer JavaScript file is downloaded, it does not block other processing processes of the browser, so these files can be downloaded in parallel with other resources on the page. Any <script> element with the defer attribute will not be executed until the DOM is loaded, whether it is an inline script or an external script file. The following example shows how the defer attribute affects script behavior:

       

These codes pop up three dialog boxes during page processing. If the browser does not support the defer attribute, the order of the pop-up dialog box is "defer", "script", and "load ". If the browser supports the defer attribute, the order of the pop-up dialog box is "script", "defer", and "load ". Note that the <script> element marked as defer is called before the onload event handle processing instead of running after the second one. If your target browser only includes Internet Explorer and Firefox 3.5, the defer script is indeed useful. If you need to support multiple cross-domain browsers, there are more consistent implementations.

Dynamic script Element

The Document Object Model (DOM) allows you to use JavaScript to dynamically create almost all HTML documents. The root cause is that the <script> element is no different from other elements on the page: Reference variables can be retrieved through the DOM, and can be moved, deleted, or created from the document. A new <script> element can be easily created using standard DOM functions:

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

The new <script> element loads the file1.js source file. This file starts to be downloaded immediately after the element is added to the page. The focus of this technology is that, no matter where the download is started, the download and running of files will not block other page processing processes. You can even put the code in the

When a file is downloaded using a dynamic Script node, the returned code is usually executed immediately (except Firefox and Opera, they will wait until all previous dynamic script nodes are executed ). This mechanism works normally when the script is of the "self-run" type. However, if the script only contains interfaces called by other scripts on the page, problems may occur. In this case, you need to track the script download and prepare it properly. You can use the dynamic <script> node to send events to obtain relevant information.

Firefox, Opera, Chorme, and Safari 3 + send a load event after the <script> node receives the event. You can listen to this event to get the notification prepared by the script:

  var script = document.createElement ("script")      script.type = "text/javascript";      //Firefox, Opera, Chrome, Safari 3+            script.onload = function(){            alert("Script loaded!");      };      script.src = "file1.js";      document.getElementsByTagName("head")[0].appendChild(script);

Internet Explorer supports another implementation method, which issues a readystatechange event. <Script> An element has a readyState attribute, and its value changes with the process of downloading an external file. ReadyState has five values:

  • "Uninitialized" default status
  • "Loading" download started
  • "Loaded" Download complete
  • "Interactive" download completed but not available
  • "Complete" all data is ready

According to Microsoft documents, in the lifecycle of <script> elements, the values of readyState may not all appear, but do not indicate which values will always be used. In practice, we are most interested in the "loaded" and "complete" statuses. Internet Explorer has different final states for the two readyState values. Sometimes the <script> element gets "loader" but never shows "complete ", however, in other cases, "complete" is not used and "loaded" is not used ". The safest way is to check the two statuses in the readystatechange event, and delete the readystatechange event handle when one of the statuses appears (ensure that the event will not be processed twice ):

  var script = document.createElement("script")      script.type = "text/javascript";      //Internet Explorer      script.onreadystatechange = function(){            if (script.readyState == "loaded" || script.readyState == "complete"){                  script.onreadystatechange = null;                  alert("Script loaded.");            }      };      script.src = "file1.js";      document.getElementsByTagName("head")[0].appendChild(script);

In most cases, you want to call a function to dynamically load JavaScript files. The following functions encapsulate the functions required for standard implementation and IE implementation:

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

This function receives two parameters: the URL of the JavaScript file and a callback function triggered when the JavaScript reception is complete. Attribute check is used to determine which event to monitor. In the last step, set the src attribute and add the <script> element to the page. The loadScript () function is used as follows:

loadScript("file1.js", function(){            alert("File is loaded!");      });

You can dynamically load many JavaScript files on the page, but note that the browser does not guarantee the order of file loading. Among all mainstream browsers, only Firefox and Opera ensure that scripts are executed in the order you specify. Other browsers will download and run different code files in the order the server returns them. You can concatenate the download operations to ensure their order, as shown below:

loadScript("file1.js", function(){            loadScript("file2.js", function(){                  loadScript("file3.js", function(){                        alert("All files are loaded!");                  });            });      });

This code starts to load file2.js only after file1.js is available. It starts to load file3.js only after file2.js is available. Although this method is feasible, it is still troublesome to download and execute many files. If the order of multiple files is very important, it is better to connect these files into a file in the correct order. Independent files can download all the code at a time (because this is asynchronous, there is no loss to using a large file ).

Dynamic Script Loading is the most common mode for non-blocking JavaScript downloads because it can be cross-browser and easy to use.

Use XMLHttpRequest (XHR) object

This technology first creates an XHR object, then downloads the JavaScript file, and then injects JavaScript code into the page with a dynamic <script> element. The following is a simple example:

  var xhr = new XMLHttpRequest();      xhr.open("get", "file1.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);                  }            }      };      xhr.send(null);

This code sends a GET request to the server for obtaining the file1.js file. The onreadystatechange event handler checks whether readyState is 4, and then checks whether the HTTP status code is valid (2XX indicates a valid response, and 304 indicates a cache response ). If you receive a valid response, create a new <script> element and set its text attribute to the responseText string received by the server. In this way, a <script> element with Inline code is created. Once a new <script> element is added to the document, the code is executed and ready for use. The main advantage of this method is that you can download JavaScript code that is not executed immediately. Because the code is returned outside of the <script> label (in other words, it is not subject to the <script> label), it will not be automatically executed after download, so that you can postpone the execution until everything is ready. Another advantage is that the same code does not cause exceptions in all modern browsers. The main limitation of this method is that JavaScript files must be placed in the same domain as pages and cannot be downloaded from CDNs (CDN indicates "Content Delivery Network (Content Delivery Network )", large web pages generally do not use XHR Script Injection Technology.

The recommended method to load a large number of JavaScript code to a page is divided into two steps: the first step contains the Code required to dynamically load JavaScript, and then load the parts required for page initialization except JavaScript. This part of the code is as small as possible and may only contain the loadScript () function. It downloads and runs very quickly without causing great interference to the page. When the initial code is ready, use it to load the rest of JavaScript. For example:

  <script type="text/javascript" src="loader.js"></script>      <script type="text/javascript">            loadScript("the-rest.js", function(){                  Application.init();            });      </script>

Place this code before the close tag of the body </body>. There are several advantages: first, as discussed earlier, this ensures that JavaScript running does not affect the display of other parts of the page. Secondly, when the second part of the JavaScript file is downloaded, all the DOM required by the application has been created and ready for access, so as to avoid extra event processing (such as window. onload) to check whether the page is ready. Another option is to directly embed the loadScript () function into the page, which can avoid another HTTP request. For example:

  <script type="text/javascript">            function loadScript(url, callback){                  var script = document.createElement ("script")                  script.type = "text/javascript";                  if (script.readyState){ //IE                        script.onreadystatechange = function(){                              if (script.readyState == "loaded" ||                              script.readyState == "complete"){                                    script.onreadystatechange = null;                                    callback();                              }                        };                  } else { //Others                        script.onload = function(){                        callback();                        };                  }                  script.src = url;                  document.getElementsByTagName_r("head")[0].appendChild(script);            }            loadScript("the-rest.js", function(){                  Application.init();            });      </script>

If you decide to use this method, we recommend that you use ''yui Compressor ''or a similar tool to narrow down the initialization script to the minimum byte size. Once the page initialization code is downloaded, you can use the loadScript () function to load the additional functions required for the page.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.