Consequences javascript can have [removed] in the

2019-03-05 02:49发布

问题:

The question is about this article: https://www.html5rocks.com/en/tutorials/speed/script-loading/

They are saying this:

<script src="//other-domain.com/1.js"></script>
<script src="2.js"></script>

Ahh, blissful simplicity. Here the browser will download both scripts in parallel and execute them as soon as possible, maintaining their order. “2.js” won’t execute until “1.js” has executed (or failed to do so), “1.js” won’t execute until the previous script or stylesheet has executed, etc etc.

Unfortunately, the browser blocks further rendering of the page while all this is happening. This is due to DOM APIs from “the first age of the web” that allow strings to be appended onto the content the parser is chewing through, such as document.write.

My question is about: "the browser blocks further rendering of the page while all this is happening".

Let's take this example:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Test</title>
</head>
<body>
    SOME HTML
    <script>
    document.write( 'bla' );

    // Synchronous delay of 5 seconds
    var timeWhile = new Date().getTime(); 
    while( new Date().getTime() - timeWhile < 5000 );
    </script>
</body>
</html>

I tested it in Firefox and Chrome and both browsers are showing "SOME HTML" after 5 seconds!! So after the javascript execution and not before the javascript execution.

What does this mean:

  • SOME HTML must be in the DOM, before executing the inline javascript, because it has synchronous behavior.
  • When the "javascript execution" starts, "SOME HTML" is not done rendering yet, because you can not see it on the screen.
  • Now the "javascript exection" will take place and the execution of javascript will block rendering.
  • After the "javascript execution," the browser will finish rendering and it will show something on the screen for the first time.

In that article they are saying: Because of the "the first age of the web", the browser will block further rendering of the page. In my opinion this has to be:

will block further "Parsing HTML" of the page

instead of

will block further rendering of the page

It's not only about the words, because you would expect totally different things if you would see it like: "will block further rendering".

In my example SOME HTML has not been rendered yet, before "executing the javascript". So IF it was about "rendering" and not directly about the "html parser" THEN document.write would add (and so render) "bla" before SOME HTML. And we all know it's not working like that.

This part is correct:

“the first age of the web” that allow strings to be appended onto the content the parser is chewing through, such as document.write

But the reason they gave for it not in my opinion:

Unfortunately, the browser blocks further rendering of the page while all this is happening. This is due to DOM APIs from “the first age of the web”

There is no reason in my example, to stop rendering and not show "SOME HTML" already before executing the document.write. It is like that, but because of totally other reasons (anyway not because of the document.write). So it has nothing to do with "rendering", but everything with the "html parser". But you can not just see "rendering" and "html parsing" as the same things and replace those terms for each other. Often html is already in the DOM, but it still takes some time, before the same HTML has been rendered.

It looks like Google is consistently treating things like that. Same as above, it looks like they are thinking: the preceding HTML is in the DOM, so let's say it also has been rendered yet.

Actually all my other posts are also about that (other situations, but same thinking of Google in my opinion). They don't discuss rendering of html, preceding to javascript execution (only what is coming after it). It looks like they are thinking: HTML preceding to javascript, is in the DOM, so let's say it has also been rendered. In my post here, they are also "confusing rendering" with "html parsing". See more posts about it here (for if you're interested in it):

Why a browser is not always finishing rendering of the preceding HTML, before executing javascript?

Google is wrong about defer?

Loading external javascript via async script tag at the end of a webpage

Why a browser is not always finishing rendering of the preceding HTML, before executing javascript?

And now you are probably thinking what the question is ;). The question is that i want to hear from you: wheter or not you agree with me about that quote in that article. And if not, please give some (good) arguments.

回答1:

I think the quote is correct, if not fully complete. Rendering is indeed blocked, but not directly; rendering depends upon the parser, which is directly blocked until the javascript finishes execution. So you are correct that the real issue is the parser being blocked, although the render is also being blocked (indirectly) due to its dependence on the parser.

In this code snippet, you can see that the first div is parsed, but not rendered; the second div is never parsed in the snippet because it is waiting for the javascript to finish.

<div id="test1">SOME HTML</div>
<script>
document.write( 'bla' );

var parsedDiv = document.getElementById("test1");
alert(parsedDiv.tagName+": "+parsedDiv.textContent);

// Synchronous delay of 3 seconds
var timeWhile = new Date().getTime(); 
while( new Date().getTime() - timeWhile < 3000 ){
   parsedDiv = document.getElementById("test2");
   if(parsedDiv)alert(parsedDiv.tagName+": "+parsedDiv.textContent);
}
</script>
<div id="test2">SOME MORE HTML</div>