Asynchronous JavaScript loading - speed up page loading. Asynchronous JavaScript vs. Lazy

Greetings, friends! Did you know that JavaScript loading is one of the biggest bottlenecks in website performance? Today my main task is to explain what a script is and how it affects the speed and performance of the site.

A browser that loads a script tag stops rendering the page until the script has loaded and executed. The page is blocked and the browser does not respond to user actions for a couple of seconds. The delay time depends on several factors:

  • configurations,
  • Internet connection speed,
  • file size and others...

For this reason, the Google PageSpeed ​​Insights website speed analyzer recommends removing rendering-blocking JavaScript code at the top of the page. A good practice is to place scripts at the bottom of the site, for example before the closing tag or set up asynchronous loading.

If the script code affects the display of the top part of the site, do not put it in a separate file, but embed it directly into the HTML.

JS can change the site's content and even redirect to a different URL. In this case, connecting the script at the end of the document will lead to the effect of “twitching” the page, loading new or changing existing elements at the top.

Applying the async and defer attributes to the script tag

Let's figure out what asynchronous and deferred work in JavaScript is and what the fundamental difference is between the async and defer attributes. But first, let's look at the sequence of processing a document with the usual inclusion of a script tag.

1 < src = "example.js" >

For this illustrative example, I will use the following conventions:

— page processing
— script loading
— script execution

Thus, the processing sequence occurs according to the following scheme:

Parsing the HTML code is interrupted while the script is loading and executing, after which it continues. There is a delay in displaying the web page.

defer attribute

The defer attribute allows the browser to start downloading js files in parallel without stopping further processing of the page. Their execution occurs after a complete parsing of the document object model (from the English Document Object Model, abbreviated DOM), while the browser guarantees consistency based on the order in which the files are connected.

1 < defer src = "example.js" >

async attribute

Support for the async attribute appeared in HTML5, it allows the browser to download js files in parallel and execute them immediately after downloading, without waiting for the rest of the page to be processed.

1 < async src = "example.js" >

Processing sequence diagram:

This is an asynchronous download. This attribute is recommended for use in scripts that do not have a significant impact on the display of the document. These include statistics collection counters (Google Analytics, Yandex Metrica), advertising network codes (Yandex Advertising Network, Google AdSense), social network buttons, and so on.

Website loading speed is one of the ranking factors in Google.

Asynchronous JavaScript connectivity reduces page load times by eliminating latency. Along with this, I recommend compressing and merging js files into one, for example, using the . Users like fast sites 😎

Modern web pages are heavily loaded with javascript files. This leads to slower loading and subsequent display of the page. In the worst conditions, the site visitor has to wait up to 30 seconds.

Speed ​​up loading html pages

Modern use of JavaScript

Modern web pages are heavily loaded with javascript files. This leads to slower loading and subsequent display of the page. In the worst conditions (slow Internet connection, a lot of javascript files), the site visitor has to wait up to 30 seconds.

HTML is designed in such a way that a web page loads by synchronously (line by line) loading in turn all the elements included in the HTML code.

There is a way out: place the Javascript lines at the end of the html document (therefore, they will be loaded after the entire page is drawn) and only after that the contents of the blocks will be displayed in the right places. It is called .

All serious projects today are trying to switch to new loading technology as quickly as possible. Moreover, it is absolutely easy.

There are several approaches. I'll start in order.

< script src= "//www.site.ru/script.js" type= "text/javascript" >

The HTML5 standard supports the ability to load scripts asynchronously, which can significantly speed up the overall page retrieval time. Just add async or defer .

< script async src= "//www.site.ru/script.js" type= "text/javascript" >

< script defer src= "//www.site.ru/script.js" type= "text/javascript" >

What is the difference between the async and defer attributes?

In both cases we get asynchronous loading of scripts. The only difference is the moment when the script starts executing. A script with the async attribute will be executed as soon as possible after it is fully loaded, but before the window object is loaded. If the defer attribute is used, the script will not violate the order of its execution in relation to other scripts and its execution will occur after the page is fully loaded and parsed, but before the DOMContentLoaded event of the document object.

Unfortunately, this mechanism does not currently work in all browsers (especially IE). Also won't work if there are document.write lines in the script.js file.

As all experts know, Google pays special attention to the loading speed of sites and lowers slow ones in search results. To help, Google has developed a special script with which you can make asynchronous javascript loading.

To use, simply replace

on

And connect the script file extsrc.js

It will turn out like this:

< script src= "//extsrcjs.googlecode.com/svn/trunk/extsrc.js" > < script extsrc= "...." >

Unfortunately, this method also does not work for files with document.write

A universal method for all browsers. Even works with document.write

In the place on the page where we need to actually display our element, create an empty div block:

< div id= "script_block" class = "script_block" >

At the very end of the page, before we insert a script for asynchronously loading files:

< div id= "script_ad" class = "script_ad" style= "display:none;" >Here is any file or script that needs to be loaded.< script type= "text/javascript" >// move it to the actual display position document. getElementById("script_block" ) . appendChild(document. getElementById("script_ad" ) ) ; // show document. getElementById("script_ad" ) . style. display = "block" ;

In the oldest versions of IE (6 and below), asynchronous loading unfortunately does not work, but there are practically no such users anymore. All other browsers and services successfully use modern accelerated loading of web pages.

There is a way out: place the Javascript lines at the end of the html document (therefore, they will be loaded after the entire page is drawn) and only after that the contents of the blocks will be displayed in the right places. It is called . All serious projects today are trying to switch to new loading technology as quickly as possible. Moreover, it is absolutely easy.

There are several approaches. I'll start in order.

script src= type= "text/javascript" >

Asynchronous loading of HTML5 script

The HTML5 standard supports the ability to load scripts asynchronously, which can significantly speed up the overall page retrieval time. Just add async or defer .

< script async src= "http://www.site.ru/script.js" type= "text/javascript" >

< script defer src= "http://www.site.ru/script.js" type= "text/javascript" >

What is the difference between the async and defer attributes?

In both cases we get asynchronous loading of scripts. The only difference is the moment when the script starts executing. A script with the async attribute will be executed as soon as possible after it is fully loaded, but before the window object is loaded. If the defer attribute is used, the script will not violate the order of its execution in relation to other scripts and its execution will occur after the page is fully loaded and parsed, but before the DOMContentLoaded event of the document object.

Unfortunately, this mechanism does not currently work in all browsers (especially IE). Also won't work if there are document.write lines in the script.js file.

Asynchronous javascript loading by Google script

As all experts know, Google pays special attention to the loading speed of sites and lowers slow ones in search results. To help, Google has developed a special script with which you can make asynchronous javascript loading.

To use, simply replace

on

And connect the script file extsrc.js

It will turn out like this:

< script src= "http://extsrcjs.googlecode.com/svn/trunk/extsrc.js" > < script extsrc= "...." >

Unfortunately, this method also does not work for files with document.write

Best working asynchronous javascript loading

A universal method for all browsers. Even works with document.write

In the place on the page where we need to actually display our element, create an empty div block:

< div id= "script_block" class = "script_block" >

At the very end of the page, before we insert a script for asynchronously loading files:

< div id= "script_ad" class = "script_ad" style= "display:none;" >Here is any file or script that needs to be loaded.< script type= "text/javascript" >// move it to the actual display position document. getElementById("script_block" ) . appendChild(document. getElementById("script_ad" ) ) ; // show document. getElementById("script_ad" ) . style. display = "block" ;

In the oldest versions of IE (6 and below), asynchronous loading unfortunately does not work, but there are practically no such users anymore. All other browsers and services successfully use modern accelerated loading of web pages.

HTML is designed in such a way that the web page is loaded sequentially line by line, loading in turn all the elements included in the html code. And if one of them is unavailable (for example, javaScript from an external site is not read), then further loading of the site stops.

When unreadable JS is at the top of the page, the visitor may not see anything at all.

Therefore, when you use JavaScript from third-party sites on your website, for example to display ads, it is highly advisable to load them asynchronously. In this case, third-party JS will not delay the loading and display of your site.

Unfortunately, not all advertising networks provide the ability to download scripts asynchronously. Therefore, in this article I will tell you how to change synchronous loading code to asynchronous. If the owner of this script does not provide this option.

Standard synchronous JS loading

Typically, calling a script from an external server looks like this:

Asynchronous script loading like Google/Adsense does

I got the idea from Google/Adsense. In order for the script to load asynchronously from the rest of the HTML code, you need to add async to the call code.

And now for the code to load asynchronously, our script call from the external server should look like this:

As you can see, everything is simple. True, this will only work in browsers that support the HTML5 standard. At the time of writing this article, there are an absolute majority of such browsers.

The proposed option is not 100% universal. Many scripts simply stop working after making these changes. According to reviews on the Internet, this method does not work if the element is used in the script document.write.

Reliable asynchronous loading option

If the first suggested option does not work for you. Then use the following recommendations. This is essentially lazy loading. Since the actual call to the script occurs at the very end of the HTML page, that is, when all the necessary content of the page is already on the screen.

In the place on the page where you want to display the result of JavaScript, you need to create an empty div block:

Then at the end of the page before the closing BODY tag we insert a script for asynchronous loading:

// JavaScript that needs to be loaded asynchronously // move it to the actual display position document.getElementById("script_block_0").appendChild(document.getElementById("script_ad_0")); // show document.getElementById("script_ad_0").style.display = "block";

If there are several advertising blocks, then for each of them you need to repeat everything, creating unique individual DIV blocks. Don't forget to change the class names and DIV IDs. In my example, it is enough to change the number zero, in the new block it needs to be replaced with 1, and so on.

This option is more complex, but it works everywhere except for very ancient browsers such as Internet Explorer 6. Which, fortunately, is practically no longer found on user computers.

) I wrote about the effect JavaScript files have on the Critical Rendering Path (CRP).


JavaScript is a blocking resource for the parser. This means that JavaScript blocks parsing of the HTML document itself. When the parser reaches the ‹script› tag (it doesn’t matter whether it’s internal or external), it stops, picks up the file (if it’s external) and runs it.

This behavior can be problematic if we load multiple JavaScript files on a page, as it increases first render time even if the document doesn't actually depend on those files.


Luckily, the element has two attributes, async and defer, which give us control over how external files are loaded and executed.

Normal execution

Before understanding the difference between these two attributes, let's look at what happens in their absence. As stated earlier, by default, JavaScript files interrupt HTML document parsing until they are received and executed.
Let's take an example where the element is located somewhere in the middle of the page:


... ... ....

This is what will happen when the parser processes the document:

HTML parsing is paused until the script is downloaded and executed, thereby increasing the amount of time until the first render.

async attribute

Async is used to indicate to the browser that the script Maybe be executed asynchronously.
The HTML parser does not need to stop when it reaches the tag to load and execute. Execution can occur after the script is received in parallel with document parsing.



The attribute is available only for files connected externally. If an external file has this attribute, then it can be loaded while the HTML document is still being parsed. The parser will pause to execute the script as soon as the script file is loaded.



defer attribute

The defer attribute tells the browser that the script should be executed after the HTML document has been completely parsed.



As with asynchronous script loading, the file can be loaded while the HTML document is being parsed. However, even if the script file is fully loaded before the parser finishes, it will not be executed until the parser finishes running.



Asynchronous, delayed or normal execution?

So, when should you use asynchronous, lazy, or normal JavaScript execution? As always, it depends on the situation and there are several questions that can help you make the right decision.

Where is the element located?

Asynchronous and lazy execution are most important when the element is not at the very end of the document. HTML documents are parsed in order, from opening to closing. If the external JavaScript file is placed immediately before the closing tag, then using async and defer becomes less appropriate, since the parser will have parsed most of the document by then and the JavaScript files will no longer have an effect on it.

Is the script self-sufficient?

For files that do not depend on other files and/or do not have any dependencies, the async attribute will be most useful. Since we don't care when the file is executed, asynchronous loading is the most suitable option.

Does the script rely on a fully parsed DOM?

In many cases, the script file contains functions that interact with the DOM. Or perhaps there is a dependency on another file on the page. In such cases, the DOM must be completely parsed before the script is executed. Typically, such a file is placed at the bottom of the page to ensure that everything has been parsed for it to work. However, in a situation where for some reason the file must be located in a different location, the defer attribute can be useful.

The script is small and dependent?

Finally, if the script is relatively small and/or depends on other files, then it may be worth defining it inline. Although the inline code blocks parsing of the HTML document, it should not be much of a problem if the document is small in size. Also, if it depends on other files, some minor locking may be needed.

Support and modern browser engines

Support for the async and defer attributes is very common:




It's worth noting that the behavior of these attributes may vary slightly between JavaScript engines. For example, in V8 (used in Chromium), an attempt is made to parse all scripts, regardless of their attributes, into a separate dedicated thread for script execution. Thus, the "parser blocking" nature of JavaScript files should be minimized by default.