This article is only technical verification, recording, communication, not for anyone. Please forgive me if I have offended you. In this paper, starting from https://vsnail.cn/static/doc/blog/browserPerformance.html

I recently read an article titled “JS must be at the bottom of the Body? Talk about browser rendering mechanics”. It starts with an interview question and then dissects the loading and rendering mechanisms of the browser.

Why is it common to put code like this at the bottom of the body? (For communication efficiency, I will make an appointment with the other party in advance that all discussions will take Chrome as an example)

Before reading the article, I would probably answer that it is to speed up the browser’s rendering of the page. But which steps, and which moments, accelerated is unknown. After reading this article, you have a general understanding of the loading and rendering mechanisms of the browser. However, some of the statements in the paper are puzzled, so they are verified in the form of experiments on some issues. Therefore, the conclusion of the conclusion of the experimental results is not right or wrong, but can only be used as a reference.

The browser’s rendering mechanism

Several concepts

  • 1. DOM: Document Object Model, the browser will parse HTML into a tree data structure, referred to as DOM.

  • 2. CSSOM: CSS Object Model, the browser will parse CSS code into a tree data structure.

  • DOM and CSSOM are Bytes → characters → tokens → Nodes → object model. In this way, the final data is generated. As shown below:

The picture above is copied from The great God, brother Vision China, please don’t come to me. I’m a front end busboy. I don’t have any money

The DOM tree building process is a deep traversal process: all children of the current node are built before the next sibling of the current node is built.

  • 4. Render Tree: DOM and CSSOM merge to generate Render Tree, as shown below:

The picture above is copied from The great God, brother Vision China, please don’t come to me. I’m a front end busboy. I don’t have any money

Like DOM, Render Tree stores CSS attributes of each node, attributes of the node itself, and child nodes of the node as a multi-fork Tree.

Note that display: None nodes are not added to the Render Tree, and visibility: hidden is, so if a node is not initially displayed, it is preferable to set display: None. You can see it here

The browser’s rendering process

  • Create/Update DOM And request CSS /image/js:

After the browser requests the HTML code, at the very beginning of DOM generation (Bytes → characters), it makes requests for CSS, images, and JS in parallel, whether they are in the HEAD or not.

Note: Initiating a js file download request does not require DOM processing to that script node, for example simple re matching can do this, although not necessarily through re. This is a misconception that many people have when they think about rendering mechanics

  • 2,Create/Update Render CSSOM:

The CSS file is downloaded and the CSSOM is built

  • 3,Create/Update Render Tree:

After all CSS files are downloaded and CSSOM is built, Render Tree is generated with DOM.

  • 4, Layout:

With Render Tree, browsers already know what nodes are in a web page, their CSS definitions, and their dependencies. The next step is called Layout, which, as the name suggests, calculates the position of each node on the screen.

  • 5, Painting:

After Layout, the browser already knows which nodes are visible, what each node’s CSS attributes are (their computed styles), and where each node is on the screen. This brings us to the final step: Painting, using the rules worked out and the graphics card to paint the content on the screen.

All of the first three of the five steps above use “Create/Update” because the DOM, CSSOM, and Render Tree may have been updated several times since the first Painting, such as when JS changed the DOM or CSS properties.

Layout and Painting are also repeated. In addition to DOM and CSSOM updates, Layout and Painting are also called to update the page after the image is downloaded.

All the above are summarized in “JS must be placed at the bottom of the Body? Talk about browser rendering mechanism”, and the word “first screen” is always mentioned in this article. For consistency, the word “first screen” in this article also means the same thing, namely, “first screen without pictures”.

Going back to the interview question,” Does the position of the script tag affect first screen time?”

In fact, from the description of the browser rendering process above, it can be seen that the position of script does not affect the time of the first screen, but it may truncate the content of the first screen so that only the upper part of the screen is displayed.

And the article “JS must be at the bottom of the Body? Talk about browser rendering mechanisms” also summarizes the following points:

  • If the position of the script label is not in the first screen range, the first screen time is not affected
  • It makes sense that all script tags should be placed at the bottom of the body
  • But for optimal performance, even the script tag at the bottom of the body will slow down the first screen because the browser will request its corresponding JS file in the first place, which takes up a limited number of TCP connections, bandwidth and even the CPU needed to run it. This is one reason why script tags have async or defer attributes.

Be confused and pay attention

I have some understanding of the browser rendering process, but there are still some confusion and caution points.

1. The first rendering time is independent of script position

From the understanding of the browser rendering process, we can see that the browser did the Painting for the first time after the Render Tree was built and the layout calculation was completed. If (and I mean if, which is probably rare) the JS you’re loading doesn’t change the structure or style of the DOM. The location of the script tag does not affect the browser’s rendering time.

We can look at the following example. We wrote a simple Web service that uses Node.js as the backend, which is really just a static resource server. We tinkered with the service a little bit, that is, if bootstrap.min.js is requested, we will wait 2 seconds before returning, and the other resources will return normally.

Example project address :github.com/btshj-snail…

At the same time, we built a simple HTML interface, which introduced three CSS, three JS. The interface code is as follows:



      
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <link rel="stylesheet" href="./style/bootstrap.min.css" />
    <link rel="stylesheet" href="./style/bootstrap-theme.min.css" />
    <link rel="stylesheet" href="./style/main.css" />
  </head>
  <body>
    <div>
      <p id="first" class="beautiful"></p>
      <p>Human nature is good in the beginning</p>
      <p>If you do not teach, you can change the way to teach</p>Once upon a time, the mother of Mencius chose her neighbors and did not learn how to divide them<br />
      <img src="./img/1000.jpeg" alt="" style="width:200px; height:200px; margin:20px;"/>
      <p id="content"></p>
    </div>

    <script src=". / js/jquery - 2.1.1. Min. Js. ""></script>
    <script src="./js/bootstrap.min.js"></script>
    <script src="./js/main.js"></script>
  </body>
</html>

Copy the code

The main. Js file has only one simple logical processing, which is to insert some words into the element with the ID content.

//main.js
document.querySelector("#content").innerHTML = "Attention, attention, not beauty.... The point is that when you see this line of text... This is what the old man really meant.. This sentence is appended dynamically through JS. When you see this sentence, it indicates that the js file is already running... In fact, without you knowing it, I secretly lazy loaded another JS..."


Copy the code

OK, everything is ready, so let’s see what happens to main.js when we return the bootstrap.min.js file with a 2 second delay.

Clone out on a project, and then enter the directory, type the command node. / server/app. Js, and then use the chrome visit http://localhost:9001/static/index.html. Next, using F12, open Chrome’s Developer tools, click On Performance, and we can easily get the browser’s rendering of the interface.

As you can see from the figure, the browser is already painting at 93.6ms. However, bootstrap.min.js data is received only after 2048ms. So the first rendering time is independent of script position.

2. Does the browser load strictly in the order of script tags?

The answer is yes without knowing anything about the browser rendering process. Otherwise, there is no guarantee of code dependency. Long ago, when we were developing, we used to put jquery files in the first reference, and other JS files that relied on the jquery library in the second reference. This was to ensure that jquery was loaded when the subsequent JS files used jquery. From this, we can also see that the browser loads js files strictly in the order of script tags.

OK, we still use the above example to verify. In the example above, we refer to the script tag of the main.js file after the script tag of bootstrap.min.js. In the background, it takes 2s to return bootstrap.min.js To perform the main. Js?

As you can see from the image above, the first paint didn’t actually render the text underneath the beautiful woman’s image. So, the first time you paint, the browser doesn’t execute main.js. So you might say, well, maybe you received the main.js file after paint. In fact, this statement, is also completely possible, but, the conclusion not to say, hey hey.. Let’s take a look at chrome’s performance rendering process and use facts to speak for themselves.

There are four records in chronological order.

First, the browser receives main.js data.

The second is the first time a browser has started paint

Third, execute the bootstrap.min.js file.

Fourth, execute the main.js file.

So you can see that downloading JS files is “concurrent”. The next js file is executed after the previous file is executed. To speed up the final rendering, load js files that are not important or not needed the first time after all the scripts. You can also add defer or async to these script tags

reference

Delai. me/code/ JS -and…

2. Case Engineering (exp-Browserpainting) github.com/btshj-snail…