javascriptcssperformancecssom

Is JavaScript execution deferred until CSSOM is built or not?


The answer to this question has been clear to me ever since I read/learned about CSSOM, until today. I can't seem to be able to find the initial article, but it explained quite clear, with examples, that JavaScript execution is deferred until CSSOM is built from all <style> and <link> tags in <head> (except those not applying, based on @media queries).
Or at least that's what I made of it at the time and I had no reason to doubt it until today.

This seems to be backed up by the bold-ed statement in this sub-chapter of Web Fundamentals / Performance, from Google:

... the browser delays script execution and DOM construction until it has finished downloading and constructing the CSSOM.

However, this statement was seriously challenged by a friendly chat on the subject with another SO user under this answer I provided, in which he proposed the following to prove the opposite:

<head>
  <script>document.write("<!--");</script>
  <style> body { background-color: red; } </style>
  -->
</head>

Ok, so let's make sure. Let's replace the <style> with

<link rel="stylesheet" type="text/css" href="test.php" />

... and make test.php hang for a few seconds:

<?php
sleep(10);
header('Content-Type: text/css');
?>

/* adding styles here would be futile */

If I am right (and js execution is deferred until CSSOM is built), the page hangs blank for 10 seconds, before building CSSOM and before executing the <script> that would comment the <link /> out and would allow the page to render.

If he is right, the js is ran as it's met and the <link /> request never leaves, because it's a comment by now.

Surprise:

Could anyone shed some light into this? What is going on?
Does it have to do with document.write?
Does it have to do with loading a .php file instead of a .css?


If it makes any difference, I tested in Chrome, on Ubuntu.

I kindly ask linking a credible (re)source or providing an eloquent example/test to back-up any answer you might consider providing.


Solution

  • This quote is true, but it means that if you place your style sheet first, and a script after it, the script will not execute until the style sheet is downloaded and parsed. See this example:

    test.php:

    <?php
    sleep(5);
    header('Content-Type: text/css');
    echo 'body {background-color: red;}';
    

    index.html:

    <link rel="stylesheet" href="test.php">
    <script>console.log('done');</script>
    

    The console.log call won't be executed until background color changes to red.

    This leads to the conclusion that building CSSOM isn't done once for all style sheets, but it's a gradual process – when browser encounters a style sheet, it downloads it, parses, and moves next. Also probably browser first makes a list of all CSS resources and adds them to the download queue, even before executing any scripts. That would explain why the request is made even though the link tag is commented by a script.