Muhammad Umer
Muhammad Umer

Reputation: 18117

How does browser loads DOM and CSSOM partially?

First let me give you simple overview how it loads, then ill ask question regarding that.

Browser Fetch HTML => parse html => create nodes => parse nodes and start converting them to Dom elements => finds style node so start creating CSSOM => on finishing parsing if there was style tag it waits to let it construct CSSOM tree => once both are finished it merges both, DOM and CSSOM, and fires DOMContentLoaded Event.

So in summary as soon as CSSOM is ready browser starts rendering and Dom can incrementally be added.

This is all fine, but how does the flow go when browser starts rendering page when not the whole html is loaded..(for example in nodejs you can partial html then wait 2s and then send more)

  1. What if there was another style tag at the bottom of the page. Not having received all html, and no css browser would start rendering, but from my understanding rendering only occurs after cssom has been completely built.
  2. What happens to script tag, if css isn't done processing script tag isn't executed and thus also stops parsing. JS is ran after CSSOM is complete.

Upvotes: 5

Views: 2607

Answers (3)

Alireza
Alireza

Reputation: 10486

A few important facts:

  • Event DOMContentLoaded is fired when the document has been fully parsed by the main parser AND the DOM has been completely built.
  • Any normal script (not async or deferred) effectively blocks DOM construction. The reason is that a script can potentially alter DOM.
  • Referencing a stylesheet is not parser-blocking nor a DOM-construction-blocker.
  • If you add a <script> (be it external or inline) after referencing a CSS, the execution (not fetching) of the script is delayed until fetching and parsing of the CSS has been finished even if the script's fetch finishes sooner. The reason is that the scripts may be dependent on the to-be-loaded CSS rules. So the browser has to wait. Only in this case, a CSS blocks the document parser and DOM construction indirectly.
  • When the browser is blocked on a script, a second lightweight parser scans the rest of the markup looking for other resources e.g. stylesheets, scripts, images etc., that also need to be retrieved. It's called "Pre-loading".

Upvotes: 0

Muhammad Umer
Muhammad Umer

Reputation: 18117

CSSOM stops parsing. Thus execution of subsequent script tags, and also delays rendering.

Script tags before style tags will execute before CSS is loaded into CSSOM from style tags afterwards.

Style tags that come after script tags will alter CSSOM. And if script accessed styles that are being altered then what it read is outdated. Order matters.

Parsing is stopped not just rendering.

JavaScript blocks parsing because it can modify the document. CSS can’t modify the document, so it seems like there is no reason for it to block parsing, right?

However, what if a script asks for style information that hasn’t been parsed yet? The browser doesn’t know what the script is about to execute—it may ask for something like the DOM node’s background-color which depends on the style sheet, or it may expect to access the CSSOM directly.

Because of this, CSS may block parsing depending on the order of external style sheets and scripts in the document. If there are external style sheets placed before scripts in the document, the construction of DOM and CSSOM objects can interfere with each other. When the parser gets to a script tag, DOM construction cannot proceed until the JavaScript finishes executing, and the JavaScript cannot be executed until the CSS is downloaded, parsed, and the CSSOM is available

.

https://hacks.mozilla.org/2017/09/building-the-dom-faster-speculative-parsing-async-defer-and-preload/

Upvotes: 1

the8472
the8472

Reputation: 43105

Things may block the DOMContentLoaded Event, but that does not prevent rendering of the incomplete page. That can be important for very long pages streamed from a slow server.

Browsers can and do interleave script execution, re-styling, rendering with the document parsing. This can be trivially shown by executing javascript in the <head> and querying the DOM, you will see that the document will not have all of its nodes (possibly not even a body element) before the DOMContentLoaded event has fired.

You have to think of document construction more as a stream than sequentially executed blocks that run to completion before the next block starts.

Upvotes: 2

Related Questions