Async Attribute and Defer Javascript - Async Pause Rendering?

Asked

Viewed 388 times

1

I was reading again about async and Defer. I realized that Async, despite loading the script asynchronously, after loading, the HTML is paused to execute the script.

Defer would work as an Async, but the execution of the Script is done after rendering the HTML.

This confirms?

And if confirmed, there being no complicating factors, using Defer instead of async promotes faster pages, or better, with faster visualization?

  • The Defer is used to indicate which script must be loaded before the event DOMContentLoaded, but it will go down in order (while the script A.js not downloaded/running, browser will not download/run the script B.js). Already the Async serves to indicate to the browser that it can continue downloading and running other scripts independent, that is, the browser will download and run without following the order (1º A.js, 2nd C.js, 3º E.js etc). And no, the defer - alone - does not have a major impact on page loading, but both (depends on the factors) yes.

  • @Valdeirpsr you say that "as long as A.js script is not downloaded/run, the browser will not download/run the script B.js.. However, I read an article, and understood that only in the EXECUTION it will do in order and not asynchronous, but to give the fetch/download it will do asynchronously.

  • https://braziljs.org/wp-content/uploads/2017/06/exec-defer-multiple.png

  • 5 scripts, . js with Defer attribute, are downloaded asynchronously, and executed synchronously (this time, without disturbing the content rendering, as the "async" would hinder).

  • Am I wrong? So, following this logic, to avoid the pause in rendering, the Defer would be the most suitable, if it could be used?

  • About the download you are correct. I looked at W3 (https://www.w3.org/TR/2011/WD-html-markup-20110113/script.html) to confirm, I was in doubt between one and the other.

Show 1 more comment

1 answer

5


HTML is not necessarily "paused", in fact what should be occurring is that some script execution that is manipulating the DOM of your pages, so it is not necessarily the async who paused something.

The async ago "the download" occur without stopping the rendering process, ie it has nothing to do with the execution of the script, but rather with the download, soon after the download the execution of a specific routine can yes affect something, it depends a lot of what you did.

The defer is similar to the event DOMContentLoaded, example:

document.addEventListener("DOMContentLoaded", function(event) {
   ....
});

Or similar to $(document).ready() jQuery, as I said are similar only and only, the attribute defer is used only for external scripts and it is worth noting also that it will be run before the event DOMContentLoaded.


When async is omitted or is false the script will have to download and run before (from the point where it was injected into the page), for example:

 <p>foo</p>
 <script src="foo.js"></script>
 <p>bar</p>

In this case <p>foo</p> would be rendered and <p>bar</p> no, in this case below:

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

The <body> would only be rendered after foo.js is downloaded and executed.

This reply from @Renan already gives a good margin of understanding (including your question):

I believe that with this all you want to solve is the rendering lock (blocking-render), so this should be a specific problem, I will explain a detail, it is probably that you have serial scripts like this:

<script src="jquery.js"></script>
<script src="foo.js"></script>
<script src="bar.js"></script>
<script src="baz.js"></script>

In this case jquery.js is downloaded and run, so only after this the download of foo.js will start, the same goes for bar.js and Baz.js, which need to wait for the previous ones to be downloaded and loaded in the order they are, however if you do this:

<script async src="jquery.js"></script>
<script async src="foo.js"></script>
<script async src="bar.js"></script>
<script async src="baz.js"></script>

All will be downloaded at almost the same time, what will differentiate is the weight and the competitive, which may vary which will be downloaded before, assuming that all depend on jQuery.js, if they are downloaded first and jquery only then all will fail, so it’s not enough to just put async to beat the render block and end up breaking the site, so I formulated this response with a suggestion of how to download asynchronous and manage to preserve the order:

Note that defer respects the order of execution and download, but it is only started after the HTML page has been downloaded completely and has been rendered, but it is also necessary to note that you can use combined Defer and async which will have the behavior of both combined:

They will load asynchronously in the order they are downloaded and executed, but only after HTML has been fully rendered


CSS and rendering lock [extra]

As I explained in this reply /a/115240/3635 CSS also affect causing rendering lock, but it does not have an attribute async to resolve, what you could experience is using the event onload only to process the CSS when properly loaded:

<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'">
<noscript><link rel="stylesheet" href="css.css"></noscript>

Or even just load it via Javascript, for example:

function loadCss(css) {
    var added = false;

    function trigger()
    {
        if (added) return;

        added = true;

        var css = document.createElement("link");

        css.onload = function() {
            document.body.appendChild(css);
        };

        css.rel = "stylesheet";
        css.src = css;
    }

    if (document.readyState !== "loading") {
        trigger();
    } else {
        document.addEventListener("DOMContentLoaded", trigger);
    }
}

loadCss("css/seu_css.css");
loadCss("css/seu_outro_css.css");
  • 1

    That’s a hell of a full answer. hahaha, thank you

Browser other questions tagged

You are not signed in. Login or sign up in order to post.