When we enter a valid URL in the browser address bar, the browser first performs DNS domain name resolution. After getting the server IP address, the browser sends a GET request to the server. When the server returns normally, the browser starts downloading and parsing HTML. This is just a summary of how browsers parse HTML.

HTML pages are mainly composed of DOM, CSS, javascript and other parts, of which CSS and javascript can be inlined or introduced in the form of scripts. Of course, IMG, iframe and other resources may also be introduced in HTML. In fact, all of these resources are embedded in HTML pages in the form of DOM tags, so the HTML parsing process summarized in this article is the DOM parsing process.

1 domThe parsing process

The entire DOM parsing process is sequential and progressive.

Sequence means parsing from the first line, line by line; Incremental means that the browser can’t wait to display the parsed part. If we do the following experiment, we can see that the first div is already rendered in the browser at the breakpoint:


      
<html>
<head>
</head>
<body>
    <div>
        first div
    </div>
    <script>
        debugger
    </script>
    <div>
        second div
    </div>
</body>
</html>
Copy the code

Since the DOM is parsed sequentially from the first line, how do we tell when the DOM is parsed? This question should often be asked in an interview. For example:

What’s the difference between window.onload and DOMContentLoaded?

It’s important to know when the DOM tree is built, especially with the jquery stack of a few years ago, because one of the prerequisites for using javascript to manipulate the DOM or bind events to the DOM is that the DOM tree has been created. When the DOM parsing of the entire HTML page is complete, the DOM tree is built. Once the DOM tree is built, the Document object sends the event DOMContentLoaded to inform you that the DOM tree is built.

HTML is parsed from the first line. If an external resource (external CSS, external javascript, image, iframe, etc.) is encountered, the corresponding resource will be requested. Will the request process block dom parsing? The answer is that it depends, some resources will, some resources won’t. The following is divided into two types according to whether the page parsing will block: blocking type and non-blocking type. Note that the symbol that distinguishes the two types of resources here is the time when the Document object sends out the DOMContentLoaded event. It is believed that only when the DOMContentLoaded event is sent out can the DOM tree construction be completed.

1.1 blocking

Resources that block DOM parsing include:

  • Inline CSS
  • Inline javascript
  • Externalize normal javascript
  • Outreach defer javascript
  • Javascript tags before the external CSS

The outgoing javascript can be marked async and defer, so there are three types: the outgoing normal javascript, the outgoing defer javascript, and the outgoing Async javascript, which will be described in detail later in this article. In the process of DOM parsing, ordinary javascript will pause parsing, request javascript and execute it, and then continue parsing the DOM tree.

As for the external defer javascript, I would like to highlight why it is also blocked. As mentioned earlier, the Document object sends the DOMContentLoaded event to indicate that the DOM tree has been built, and the defer javascript is requested and executed before the event is sent, so it is also classified as blocking, but you need to know that The javascript in defer is actually requested and executed between the completion of the DOM tree and the delivery of the DOMContentLoaded event, but if you think about it differently,

Another thing to note is the external CSS that precedes javascript tags. In fact, CSS resources should not block the dom tree construction process. After all, CSS only affects the DOM style, not the DOM structure.

The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.

But the reality is that building the DOM tree is blocked by javascript, and javascript execution might use an API like window.getComputedStyle () to get the DOM style, for example:

const para = document.querySelector('p');
const compStyles = window.getComputedStyle(para);
Copy the code

Therefore, browsers will typically execute the outgoing CSS requests that precede the

theseblockingAfter the resource request is completed and executedThe dom treeThe parsing is completedocumentThe object will send itDOMContentLoadedEvent, representsThe dom treeBuild complete.

1.2 Non-blocking type

Resources that do not block DOM parsing include:

  • External CSS after javascript tags
  • image
  • iframe
  • Outreach async javascript

The DOMContentLoaded event is issued after the DOM tree is parsed, and there are two types of external CSS resources: those before and after the

The DOMContentLoaded event is used to indicate that the DOM tree is completed. The answer is window.onload. Since this event is distributed too late, we usually don’t use it, but rather use DOMContentLoaded to manipulate the DOM as early as possible.

Image, iframe, and external Async javascript also do not block dom tree construction. So what’s async javascript? The next section takes a look at outbound javascript in general.

2 Outreach javascriptThe loading process

An HTML page can be introduced with either inline or inline javascript, which can be divided into:

  • Externalize normal javascript
<script src="indx.js"></script>
Copy the code
  • Outreach defer javascript
<script defer src="indx.js"></script>
Copy the code
  • Outreach async javascript
<script async src="indx.js"></script>
Copy the code

The first of these is external plain javascript, which blocks the parsing of HTML. Each

Externalize normal javascript

Outreach defer javascript
html
<script>
html
javascript
Outreach defer javascript
DOMContentLoaded
Outreach defer javascript

Outreach async javascript
html
download
html
html
html
javascript
html

html
Outreach async javascript
DOMContentLoaded
Outreach async javascript
DOMContentLoaded
stackoverflow
This problem

And just to be clear, these graphs are referenced here.

3 DOMContentLoadedCompatibility issues

DOMContentLoaded was originally proposed by Firefox, and other browsers have found it useful to support it, but with slightly different features. For example, in Opera, javascript executes without waiting for an external CSS to load. Until HTML5 came out and standardized DOMContentLoaded, according to the HTML5 standard, the that appears before the current

So how do you solve DOMContentLoaded compatibility issues before all browsers are standardized? Ready () : ready() : ready() : ready() : ready() : ready()) : ready() : ready(); DOMContentedLoaded is currently supported by IE9 using the compatibility method described in MDN: DOMContentLoaded, and ie8 environments can check the document.readyState state to confirm that the DOM tree is built. Document. readyState includes three states:

  • Loading-html document is loading
  • Interactive – HTML documents have been loaded and parsed, but images and other resources have not been loadedDOMContentLoaded
  • Complete – All resources are loaded, equivalent towindow onload

Therefore, we simulate the DOMContentLoaded time point by judging the state of document. readyState to be interactive. But one thing to note here is that the.ready() method, for example, might be called in one of the following places:

  • Inline javasctipt
  • Externalize normal javascript
  • Outreach defer javascript
  • Outreach async javascript

The state of document. readyState must be loading. The state of document. readyState must be interactive or completed. Because the external async javascript does not block DOM parsing, we need to listen for changes in document.readystate in order to fully cover the previous four cases:

if (document.readystate === 'interactive'
    || document.readystate === 'complete') {
        // Call the ready callback
} else {
    document.onreadystatechange = function () {
        if (document.readystate === 'interative') {
            // Call the ready callback}}}Copy the code

4 references

Mainly refer to the following articles, recommended reading:

  1. Page lifecycle: DOMContentLoaded, load, beforeunload, unload
  2. DOMContentLoaded and stylesheets
  3. Script tag: Async vs defer Attributes
  4. MDN: DOMContentLoaded
  5. MDN: readystatechange
  6. Replace jQuery’s Ready() with Plain JavaScript