Performance optimizations for JavaScript: loading and executing

Source: Internet
Author: User
Tags blank page

Overview

Whether the current JavaScript code is inline or in an out-of-chain file, the download and rendering of the page must stop waiting for the script to complete. The longer the JavaScript execution takes, the longer the browser waits to respond to user input. The reason that the browser blocks when downloading and executing scripts is that the script may change the namespace of the page or JavaScript, which affects the content of the page behind it. A typical example is the use of a page document.write() . For example, listing 1

Listing 1 JavaScript Code inline example

When the browser encounters <script> 标签时,当前 HTML 页面无从获知 javascript  是否会向 <p>  标签添加内容,或引入其他元素,或甚至移除该标签。因此,这时浏览器会停止处理页面,先执行  代码,然后再继续解析和渲染页面。同样的情况也发生在使用  src  属性加载  javascript javascript的过程中,浏览器必须先花时间下载外链文件中的代码,然后解析并执行它。在这个过程中,页面渲染和用户交互完全被阻塞了。

Back to top of page

Script Location

The HTML 4 specification indicates that a <script> label can be placed in or in an HTML document and is allowed to <body> occur more than once. Web developers are generally accustomed to loading the outer-chain JavaScript in, and then using <link> tags to load the outer-chain CSS files or other page information. For example, listing 2

Listing 2 Examples of inefficient script locations

However, this conventional approach hides serious performance problems. In the example in Listing 2, when the browser resolves to the <script> label (line 4th), the browser stops parsing the content, and the script file is first downloaded, and the code is executed, which means that the Styles.css style files and <body> tags after it cannot be loaded because <body> The label cannot be loaded, so the page will not be rendered naturally. So before the JavaScript code is fully executed, the page is blank. Figure 1 describes the download process for script and style files during page loading.

Figure 1 The loading and execution of JavaScript files blocks the download of other files

We can find an interesting phenomenon: the first JavaScript file starts to download, and at the same time blocks the download of other files on the page. In addition, there is a delay from the completion of the Script1.js download to the beginning of the Script2.js download, which is exactly the Script1.js file execution process. Each file must wait until the previous file is downloaded and executed before the download begins. In the process of downloading these files individually, the user sees a blank page.

Starting with IE 8, Firefox 3.5, Safari 4 and Chrome 2, JavaScript files are allowed to be downloaded in parallel. This is good news because <script> the label does not block other tags when it downloads external resources <script> . Unfortunately, the JavaScript download process still blocks downloads of other resources, such as style files and pictures. Although the download process for scripts does not affect each other, the page must still wait for all JavaScript code to download and complete before continuing. Therefore, although the latest browser improves performance by allowing parallel downloads, the problem is not yet fully resolved, and script blocking remains a problem.

Because the script blocks the download of other resources on the page, it is recommended that all tags be placed at the bottom of the label as much as possible to minimize the <script> <body> impact on the entire page download. For example, listing 3

Listing 3 recommended Code placement examples

This code shows the recommended location for placing labels in an HTML document <script> . Although a script download blocks another script, most of the page's content is downloaded and displayed to the user, so the page download does not appear too slow. This is the first rule to optimize JavaScript: Put the script at the bottom.

Back to top of page

Organizing scripts

Because <script> page rendering is blocked at the initial download of each label, reducing the number of labels included in the page <script> can help improve the situation. This is not only for outer-chain scripts, but also for the number of inline scripts to be limited. Each time a browser encounters a tag during parsing of an HTML page, a <script> delay is caused by the execution of the script, so minimizing the latency will significantly improve the overall performance of the page.

This problem is slightly different when dealing with an outside-chain JavaScript file. Given the additional performance overhead associated with HTTP requests, downloading a single 100Kb file will be faster than downloading 5 20Kb files. In other words, reducing the number of scripts on the page will improve performance.

Typically a large web site or application relies on several JavaScript files. You can combine multiple files into one, so you <script> can reduce performance consumption by simply referencing a label. The work of file merging can be done through offline packaging tools or some real-time online services.

A special reminder is that placing an inline script after referencing an outer-chain style sheet <link> causes the page to block to wait for the stylesheet to be downloaded. This is done to ensure that the inline script obtains the most accurate style information when it executes. Therefore, it is recommended that you do not immediately follow the tag in the inline script <link> .

Back to top of page

Non-blocking scripts

Reducing the size of JavaScript files and limiting the number of HTTP requests is not always feasible on a feature-rich Web application or large Web site. The richer the Web app is, the more JavaScript code is needed, although downloading a single large JavaScript file produces only one HTTP request, which locks the browser for a long time. To avoid this, it is necessary to incrementally load JavaScript files into the page through some specific techniques that do not block the browser in some way.

The secret of a nonblocking script is that the JavaScript code is loaded after the page is loaded. This means that the window script is downloaded after the object's onload event is triggered. There are several ways to achieve this effect.

Deferred load script

HTML 4 <script> defines an extended property for the tag: defer . Deferproperty indicates that the script contained in this element does not modify the DOM, so the code can safely defer execution. deferproperties are supported only by browsers of IE 4 and Firefox 3.5 later, so it is not an ideal cross-browser solution. In other browsers, defer attributes are ignored directly, so the <script> labels are handled in the default way, which in other words can cause blocking. However, this is still a useful solution if your target browser supports it. Listing 4 is an example

Listing 4 Defer properties using the method Example
<script type= "Text/javascript" src= "Script1.js" defer></script>

deferlabels with attributes <script> can be placed anywhere in the document. The corresponding JavaScript file will start downloading when the page resolves to the <script> label, but will not execute until the DOM is loaded, that is, onload before the event is triggered. When a defer JavaScript file with attributes is downloaded, it does not block other browsers ' processes, so such files can be downloaded in parallel with other resource files.

Any defer element with attributes <script> will not be executed until the DOM has finished loading, either inline or outside the chain script. The example in Listing 5 shows defer how the properties affect script behavior:

Listing 5 Effects of the Defer property on script behavior

This code pops up three dialog boxes during page processing. Browsers that do not support defer properties have the following popup order: "Defer", "script", "load". deferon browsers that support properties, the order of popup is "script", "defer", and "load". Note that the defer element with the attribute is not followed by the <script> second, but onload is called before the event is triggered.

If your target browser includes only Internet Explorer and Firefox 3.5, then the defer script is really useful. If you need to support multiple browsers across domains, there is a more consistent way to implement them.

HTML 5 <script> defines a new extended property for the tag: async . It works the defer same way that scripts can be loaded and executed asynchronously, without blocking the loading of the page because of the load script. It is important to note, however, that async JavaScript scripts are executed once they have been downloaded, so it is likely that they are not executed in the original order. If a JavaScript script has dependencies before and after it, there is a async good chance that an error will occur.

Dynamic scripting elements

The Document Object Model (DOM) allows you to dynamically create almost all of the document content of HTML using JavaScript. <script>elements, like other elements of a page, can be easily created with standard DOM functions:

Listing 6 creating <script> elements with standard DOM functions
var script = document.createelement ("script");   Script.type = "Text/javascript";   SCRIPT.SRC = "Script1.js";   document.getElementsByTagName ("Head") [0].appendchild (script);

The new <script> element loads the script1.js source file. This file starts downloading immediately after the element is added to the page. The point of this technique is that no matter where the download is initiated, the download and operation of the file does not block other page processing processes. You can even place the code in part without affecting the rest of the page code (except for the HTTP connection used to download the file).

When a file is downloaded using a dynamic script node, the returned code is usually executed immediately (except for Firefox and Opera, they will wait until all the previous dynamic script nodes have been executed). This mechanism works fine when the script is a "self-running" type, but it can cause problems if the script contains only the interfaces that are called by other script calls on the page. In this case, you need to track the script download complete and be prepared properly. Events can be <script> emitted using dynamic nodes to get information about them.

Firefox, Opera, Chorme, and Safari will <script> issue an event after the node is received onload . You can listen to this event to get the script ready for notification:

Listing 7 loading JavaScript scripts by listening for onload events
var script = document.createelement ("script") Script.type = "Text/javascript";//firefox, Opera, Chrome, Safari Script.onload = function () {    alert ("Script loaded!");}; SCRIPT.SRC = "Script1.js";d ocument.getelementsbytagname ("Head") [0].appendchild (script);

Internet Explorer supports an alternative implementation, which emits an readystatechange event. <script>element has an readyState attribute whose value changes as the process of downloading an external file. readyStateThere are five kinds of values:

    • "Uninitialized": Default state
    • "Loading": Download start
    • "Loaded": Download complete
    • "Interactive": Download complete but not yet available
    • "Complete": all data is ready.

In the Microsoft documentation, <script> these values do not necessarily appear in the lifetime of the element, readyState but do not indicate which values are always used. In practice, we are most interested in the "loaded" and "complete" states. Internet Explorer readyState does not agree on the final state of these two values, sometimes the <script> element gets "loader" but never "complete", but in other cases "complete" is not used to "loaded". The safest way to readystatechange do this is to check both states in an event, and when one of these states is present, delete the readystatechange event handle (which guarantees that the event will not be processed two times):

Listing 8 loading JavaScript scripts by checking the ReadyState state
var script = document.createelement ("script") Script.type = "Text/javascript";//internet Explorerscript.onreadystatechange = function () {     if (script.readystate = = "Loaded" | | script.readystate = = "complete ") {           script.onreadystatechange = null;           Alert ("Script loaded.");}     ; SCRIPT.SRC = "Script1.js";d ocument.getelementsbytagname ("Head") [0].appendchild (script);

In most cases, you want to invoke a function to implement the dynamic loading of a JavaScript file. The following function encapsulates the functionality required by the standard implementation and IE implementations:

Listing 9 Encapsulation by function
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 that fires when the JavaScript receive is complete. The property check is used to determine which event to monitor. The final step is to set the src properties and <script> add the elements to the page. This loadScript() function is used in the following ways:

List of Loadscript () functions using the method
Loadscript ("Script1.js", function () {    alert ("File is loaded!");});

You can load many JavaScript files dynamically in the page, but be aware that the browser does not guarantee the order in which the files are loaded. Of all the major browsers, only Firefox and Opera guarantee that the scripts are executed in the order you specify. Other browsers will download and run different code files in the order in which they are returned by the server. You can concatenate the download operations together to ensure their order, as follows:

Listing 11 loading multiple JavaScript scripts with the Loadscript () function
Loadscript ("Script1.js", function () {    loadscript ("Script2.js", function () {        loadscript ("Script3.js", function () {            alert ("All Files is loaded!");});});    

This code waits until Script1.js is available to start loading script2.js, and so script2.js starts loading script3.js after it is available. While this approach works, it's still a bit cumbersome to download and execute a lot of files. If the order of multiple files is important, a better way is to connect the files to a file in the correct order. Standalone files can download all the code at once (since this is done asynchronously, there is no loss in using a large file).

Dynamic scripting loads the most common pattern in non-blocking JavaScript downloads, because it can be cross-browser and easy to use.

Using XMLHttpRequest (XHR) objects

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

Listing 12 loading JavaScript scripts with XHR objects
var xhr = new XMLHttpRequest (), Xhr.open ("Get", "Script1.js", true); Xhr.onreadystatechange = function () {    if ( Xhr.readystate = = 4) {        if (xhr.status >= && Xhr.status < | | 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 to get the Script1.js file. onreadystatechangethe event handler check readyState is not 4, and then check that the HTTP status code is not valid (2XX indicates a valid response, and 304 represents a cached response). If a valid response is received, a new element is created <script> and its Text property is set to the string received from the server responseText . Doing so will actually create an element with inline code <script> . Once the new <script> element is added to the document, the code is executed and ready to be used.

The main advantage of this approach is that you can download JavaScript code that is not executed immediately. Since the code is returned <script> outside the label (in other words, not <script> tagged), it is not automatically executed after it is downloaded, which allows you to defer execution until everything is ready. Another advantage is that the same code does not throw an exception in all modern browsers.

The main limitation of this method is that the JavaScript file must be placed in the same domain as the page and cannot be downloaded from the CDN (Cdn refers to the content Delivery network), so a large web page usually does not use XHR script injection technology.

Performance optimizations for JavaScript: loading and executing

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.