📜 ⬆️ ⬇️

Asynchronous vs delayed javascript

In my article “Understanding the Critical Rendering Path” ( translation of the article ), I wrote about the effect of JavaScript files 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> (whether it is internal or external), it stops, takes the file (if it is external), and starts it.

This behavior can cause problems if we load several JavaScript files on the page, as this increases the time of the first rendering, even if the document is not really dependent on these files.


Fortunately, the <script> element has two async and defer attributes that give us the ability to control how external files are loaded and executed.



Normal execution


Before understanding the difference between these two attributes, let's see what happens in their absence. As mentioned earlier, by default JavaScript files interrupt the parsing of an HTML document until they are received and executed.
Take an example in which the <script> element is located somewhere in the middle of the page:


 <html> <head> ... </head> <body> ... <script src="script.js"> .... </body> </html> 

Here is what happens when the parser processes the document:



HTML parsing pauses until the script is loaded and executed, thereby increasing the amount of time until the first rendering.


async attribute


Async used to indicate to the browser that the script can be executed asynchronously.
The HTML parser does not need to stop when it reaches the <script> for loading and execution. Execution may occur after the script is received in parallel with the parsing of the document.


 <script async src="script.js"> 

Attribute is available only for files that connect externally. If the external file has this attribute, then it can be loaded while the HTML document is still parsed. The parser will be suspended for script execution as soon as the script file is loaded.



defer attribute


The defer attribute indicates to the browser that the script should be executed after the HTML document is completely parsed.


 <script defer src="script.js"> 

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



Asynchronous, deferred or normal execution?


So, when should asynchronous, deferred, or normal JavaScript be used? As always, it depends on the situation and there are several questions that will help you make the right decision.


Where is the <script> element?


Asynchronous and deferred execution are most important when the <script> element is not at the very end of the document. HTML documents are parsed in order, from opening <html> to closing it. If an external JavaScript file is placed immediately before the closing </body> , then using async and defer becomes less relevant, since the parser will have already parsed most of the document by that time, and the JavaScript files will no longer affect it.


Is the script self-contained?


For files that are independent of other files and / or have no dependencies, the async attribute will be most useful. Since it does not matter to us when the file is executed, asynchronous loading is the most suitable option.


Does the script rely on a fully disassembled 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. As a rule, such a file is placed at the bottom of the page to make sure that everything has been disassembled for its operation. However, in a situation where, for whatever reason, the file must be placed elsewhere - the defer attribute may be useful.


Is the script small and dependent?


Finally, if the script is relatively small and / or depends on other files, then it may be worth defining it inline. Despite the fact that the embedded code blocks the parsing of HTML-document, it should not be much hindered if its size is small. In addition, if it depends on other files, a slight lock may be necessary.


Support and modern browser engines


Support for the async and defer very common:




It is worth noting that the behavior of these attributes may differ slightly in different JavaScript engines. For example, in V8 (used in Chromium), an attempt was made to parse all the scripts, regardless of their attributes, on a separate dedicated thread to execute the script. Thus, the “blocking parser” nature of JavaScript files should be minimized by default.


')

Source: https://habr.com/ru/post/323790/


All Articles