Attribute Async and Defer Javascript - Async pause rendering?

1

I was reading again, about async and defer. I noticed that Async, although loading the script asynchronously, after loading, the HTML is paused to execute the script.

Defer would work as an Async, but script execution is done after HTML rendering.

Does this confirm?

And if confirmed, if there are no complicating factors, using defer instead of async promotes faster pages, or better, faster viewing?

    
asked by anonymous 04.06.2018 / 00:54

1 answer

4

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

The async makes "the download" occurs without stopping the rendering process, ie it does not have to be with the execution of the script, but with the download, soon after downloading the execution of a specific routine can indeed affect something, it depends a lot on what you did.

The defer is similar to the event DOMContentLoaded , example:

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

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

When async is omitted or is false the script will have to download and execute 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> not, in this case below:

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

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

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

I think that with this all you want to solve is blocking-rendering, so this should be a specific problem, I'll explain one detail, it's 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 executed, then only after that will the download of foo.js be started, the same goes for bar.js and baz.js, who need to wait for the previous ones to be downloaded and loaded in the order they 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>

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

Note that defer respects the run and download order, but it only starts after the HTML page has been completely downloaded and rendered, but it should also be noted that you can use combined defer and async that will have the behavior of both combined:

  

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

CSS and the render lock

As I explained in this response link the CSS also affect causing the render lock, but it does not have an attribute async to solve, what you could try is to use the onload event to only render the CSS when it was 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");
    
04.06.2018 / 01:34