Browser Rendering HTML Process

Browser resource loading process

Let’s start with two questions:

  • How does the browser know which resources should be loaded?
  • In what order does the browser load these resources?

When the browser intercepts a page, it will do the following four things in order

  1. First, all the resources that need to be loaded will be classified.
  2. Then decide the loading permission of the resource according to the security policy related to the browser.
  3. Then calculate and sort the loading priority of each resource.
  4. The last step is to load resources according to the loading priority order.

Resource classification

Chrome browser will classify resources into 14 categories, as shown in the following table.

TypeIntroduction
kMainResourceis the main resource, html page file resources belong to this type
kImageVarious Image Resources
kCSSStyleSheetAs the name suggests, it is Cascading Style Sheet css resource
kScriptScript resources, such as js resources
kFontFont resources, such as font sets commonly used in web pages. Woff resources
kRawMixed-type resources, which are the most common ajax requests
kSVGDocumentSVG scalable vector graphics file resource
kXSLStyleSheetExtended Stylesheet Language XSLT is a transformation language. You can refer to w3c XSL to learn about this type
kLinkPrefetchLink prefetch for HTML5 pages, such as dns-prefetch. Details below
kTextTracksubtitle resources for video, - ie "tags
kImportResourceHTML Imports, import an HTML file into another HTML doc, such as ". For more information, please refer to the relevant doc.
kMediaMultimedia resources, both video or audio
kManifestHTML5 Application Cache Resources
kMockReserved Test Types

Security policy check

Content Security Policy (CSP) is a Whitelist system provided by browsers. Developers improve the security of web pages by configuring it to tell the browser about loading and execution restrictions for various external resources. One of the most commonly used applications is to prevent XSS attacks by restricting the loading of untrusted domain name scripts. CSP can be configured in two ways. The first is to restrict through the Content-Security-Policy field in the HTTP request header of the page. As shown in the figure below, this is the request header of the www.google.com page:

流程流程

The second is to set it through the “tag.” is configured in the way of key-value. Here are a few specific application examples to introduce.

  1. To prevent XSS:
1
2
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; style-src nos.netease.com kaola.com;">
Copy the code

The above’script-src ‘represents script resources;’ style-src ‘represents style resources;’ self ‘represents only trust foreign resources under the current domain name, and all resources under other domains will be intercepted;’ nos.netease.com kaola.com 'represents trust nos.netease.com and kaola.com resources under these two domain names. So the meaning of the above label is: for script resources only trust the domain, for style resources, in addition to the domain will load nos.netease.com and kaola.com under these two domain names.

  1. For site request protocol upgrade transition (http to https):
1
2
<meta http-equiv="Content-Secur****ity-Policy" content="upgrade-insecure-requests">
Copy the code

The meaning of’upgrade-insect-requests’ above is just like the literal meaning: upgrade all non-secure requests. When this meta tag is added, the browser will automatically upgrade all htttp in the https page to https. For example, when we need to transform the whole site from http to https, for a large number of original http resources, the request will be directly forced to send in SSL encryption such as https or wss without reporting an error. Of course, if the resource server does not support SSL encryption such as https, then the resource will not be loaded.

  1. Used to block Mixed Content:
1
2
<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
Copy the code

Mixed Content is the http request made in the https site mentioned in the second example. This type of mixed non-secure request content in a secure link is called mixed content. When such a request occurs, we can find the corresponding warning message in the browser Console, as shown in the figure below.

流程流程

Mixed content will reduce the security and User Experience of HTTPS websites. However, it is slightly reassuring that browsers will directly block Blend Mode requests for resource types that may pose a greater threat to security, such as script resources, as shown in the figure below. However, for resources such as images, audio, video, etc., it will only warn, but will not prevent them from loading.

流程流程

For websites with extremely high security requirements, all types of non-secure link requests can be blocked by the above tags, so that resources including pictures, audio, video and so on will also be intercepted and reported errors. Of course, there are many other functions for the setting of Content-Security-Policy. You can useMDNTo learn more.

Resource priority calculation

The priority of resources is divided into ** 5 levels **. The naming and description of this ** 5 level ** may be different on different materials. Mainly because the data itself may be from the ** network level **, ** browser kernel ** or ** client console display ** one of these three directions. Although these three directions have different names for this ** 5 level **, they are all one-to-one correspondence. ** Network level **, 5 levels are: Highest, Medium, Low, Lowest, Idle; ** Browser kernel **, 5 levels are: VeryHigh, High, Medium, Low, VeryLow; ** Client Console Display **, 5 levels are: Highest, High, Medium, Low, Lowest;

The following is a research direction based on the browser kernel to introduce the resource priority calculation process of the browser:

  • The first step is to set the default priority according to the type of resource. For each type of resource browser, there is a default loading priority rule:
  1. html, css, font these three types of resources have the highest priority;
  2. Then the preload resource (via``Tag preload), script, xhr request;
  3. Followed by pictures, voice, and video;
  4. The lowest isprefetchPre-read resources.
  • The second step is to adjust the priority according to certain actual rules. After the initial priority is set, the browser will adjust the priority according to the actual properties of the resource and the location in the doc to determine the final loading priority order. Adjustment rules for several common resource types are as follows:
  1. For ** XHR requests ** resources: Adjust the priority of ** synchronous XHR requests ** to the highest. XHR requests can be divided into synchronous requests and asynchronous requests, and the browser will raise the priority of synchronous requests to the highest level in order to obtain data as soon as possible and speed up the display of the page.
  2. For ** image ** resources: The priority will be changed according to whether the image is in the visible view. The default priority of image resources is Low. In order to improve the user’s first screen experience, modern browsers will calculate whether the image resource is in the first screen visible view when rendering. If so, the priority of this part of the image in viewport resource will be raised to High.
  3. For ** script ** resources: The browser will divide the script into three categories according to its location and attribute tab, and set the priority separately. First, the priority of scripts with defer/async attribute tab added will all be reduced to Low. Then, for scripts without this attribute added, they can be divided into two categories according to whether the position of the script in the doc is before or after the first image displayed by the browser. Before ’ (marked early **) ’ it will be set to High priority, after ’ (marked late **) ’ it will be set to Medium priority.

Load or block resources according to the security policy and priority calculated above.

Browser rendering process

** Critical Render Path **

When it comes to page rendering, there are several concepts that are very relevant, the most important is the critical rendering path, and several other concepts can be expanded from it, which is explained slightly below.

Critical Rendering Path refers to the content related to the current user operation. For example, when a user just opens a page, the first screen display is the content related to the current user operation, specifically, the browser receives resources such as HTML, CSS, and JavaScript and processes them to render a web page.

Understanding the process and principle of browser rendering is largely to optimize the critical rendering path, but optimization should be a solution to specific problems, so there are no fixed rules for optimization. For example, in order to ensure the fastest display of the first screen content, progressive page rendering is usually mentioned, but in order to progressive page rendering, resources need to be split, so what granularity to split, whether to split, different pages, different scenes strategy is different. The determination of specific solutions should consider not only experience issues, but also engineering issues.

From a time-consuming perspective, the browser requests, loads, and renders a page, and the time is spent below五件事情Above:

  1. DNS query
  2. TCP connection
  3. HTTP requests are responses
  4. Server response
  5. Client Rendering

This article discusses the fifth part, that is, the rendering of content by the browser. This part (render tree construction, layout, and rendering) can be divided into the following五个步骤

  1. Process HTML tags and build DOM tree.
  2. Process CSS tags and build CSSOM trees.
  3. Merge DOM and CSSOM into one render tree.
  4. Layout according to the rendering tree to calculate the geometry information of each node.
  5. Draw each node onto the screen.

It’s important to understand that these five steps are not necessarily done in order at once. If the DOM or CSSOM is modified, the above process needs to be repeated in order to calculate which pixels need to be re-rendered on the screen. In real pages, CSS and JavaScript tend to modify the DOM and CSSOM multiple times. Here’s a look at how they affect it.

** Blocking Rendering: CSS

When talking about blocking of resources, we should be clear that modern browsers always load resources in parallel. For example, when the HTML parser (HTML Parser) is blocked by a script, although the parser will stop building the DOM, it will still recognize the resource behind the script and preload it.

At the same time, due to the following two points:

  1. By default, CSS is treated as a rendering-blocking resource, which means that the browser will not render any processed content until the CSSOM is built.
  2. JavaScript can read and modify not only DOM properties, but also CSSOM properties.

When there are blocking CSS resources, the browser will delay the execution of JavaScript and DOM construction. In addition:

When the browser encounters a script tag, the DOM build will pause until the script finishes executing.
2. JavaScript can query and modify DOM and CSSOM.
3. When CSSOM is built, JavaScript execution will pause until CSSOM is ready.

Therefore, the position of the script tag is very important. In actual use, you can follow the following two principles:

  1. CSS first: In the introduction order, CSS resources come before JavaScript resources.
  2. JavaScript should affect the construction of the DOM as little as possible.

Browsers are evolving faster and faster (the current official stable version of the Chrome is 61), and the specific rendering strategy will continue to evolve, but after understanding these principles, you can figure out the logic of its evolution. Let’s take a look at how CSS and JavaScript specifically block resources.

CSS

1
2
<style> p { color: red; }</style>
<link rel="stylesheet" href="index.css">

Such link tags (whether inline or not) will be treated as blocking rendering resources, and the browser will prioritize these CSS resources until the CSSOM is built.

In the critical rendering path of Render-Tree, it is required to have both DOM and CSSOM before building the render tree. That is, both HTML and CSS are rendering-blocking resources. HTML is obviously necessary, because the content, including the text we want to display, is stored in the DOM, so we can figure it out from CSS.

The easiest thing to think of is of course to simplify CSS and provide it as soon as possible. In addition, you can also use media types and media queries to unblock rendering.

1
2
3
<link href="index.css" rel="stylesheet">
<link href="print.css" rel="stylesheet" media="print">
<link href="other.css" rel="stylesheet" media="(min-width: 30em) and (orientation: landscape)">

The first resource will load and block.
The second resource sets the media type, loads but does not block, and the print declaration is only used when printing web pages.
The third resource provides media queries that block rendering when conditions are met.

JavaScript

The situation with JavaScript is a bit more complicated than CSS. Observe the following code:

1
2
3
4
5
6
7
8
9
10
11
<p>Do not go gentle into that good night,</p>
<script>console.log("inline")</script>
<p>Old age should burn and rave at close of day;</p>
<script src="app.js"></script>
<p>Rage, rage against the dying of the light.</p>

<p>Do not go gentle into that good night,</p>
<script src="app.js"></script>
<p>Old age should burn and rave at close of day;</p>
<script>console.log("inline")</script>
<p>Rage, rage against the dying of the light.</p>

Such script tags will block HTML parsing, whether inline-script or not. The above P tag will be parsed from top to bottom, and this process will be planned (loaded and executed) by two JavaScript paragraphs respectively.

So in practical projects, we often put resources at the bottom of the doc.

** Change blocking mode: defer

Why put the defer and async methods of script loading later? Because these two methods appear, all due to the existence of the blocking conditions mentioned earlier. In other words, defer and async methods can change the previous blocking situations.

First, note that the async and defer attributes are not valid for inline-script, so the code for the three script tags in the following example will be executed from top to bottom.

1
2
3
4
5
6
7
8
9
10
<! -- output 1 2 3 in top-to-bottom order -- >
<script async>
console.log("1");
</script>
<script defer>
console.log("2");
</script>
<script>
console.log("3");
</script>

Therefore, the content discussed in the following two sections is for script tags with the src attribute set.

defer

1
2
3
<script src="app1.js" defer></script>
<script src="app2.js" defer></script>
<script src="app3.js" defer></script>

The defer attribute indicates the delayed execution of the introduced JavaScript, that is, the HTML does not stop parsing when the JavaScript is loaded, and the two processes are parallel. After the entire document is parsed and the transfer-script is loaded (the order of these two things is independent), all JavaScript code loaded by the transfer-script will be executed, and then the DOMContentLoaded event will be triggered.

Defer does not change the execution order of the code in the script, and the sample code will be executed in the order of 1, 2, and 3. Therefore, there are two differences between defer and ordinary scripts: the HTML parsing is not blocked when loading JavaScript files, and the execution stage is placed after the HTML tag parsing is completed.

async

1
2
3
<script src="app.js" async></script>
<script src="ad.js" async></script>
<script src="statistics.js" async></script>

The async attribute indicates that the imported JavaScript is executed asynchronously. The difference between defer and defer is that if it has already been loaded, it will start executing - whether it is in the HTML parsing stage or after DOMContentLoaded is triggered. It should be noted that JavaScript loaded in this way will still block the load event. In other words, async-script may be executed before or after DOMContentLoaded is triggered, but it must be executed before load is triggered.

As can be seen from the previous paragraph, the execution order of multiple async-scripts is uncertain. It is worth noting that when dynamically adding script tags to document, the async attribute defaults to true. We will continue this topic in the next section.

document.createElement

Scripts created using document.createElement are asynchronous by default, as shown below.

1
console.log(document.createElement("script").async); // true

Therefore, introducing JavaScript files by dynamically adding script tags will not block the page by default. If you want to execute synchronously, you need to artificially set the async attribute to false.

What if I use document.createElement to create a link tag?

1
2
3
4
const style = document.createElement("link");
style.rel = "stylesheet";
style.href = "index.css";
document.head.appendChild(style); // 阻塞?

In fact, this can only be determined experimentally. What is known is that Chrome have不会阻塞渲染, Firefox, IE were blocked in the past, what will happen now I didn’t experiment.

**document.write

The link or script tag added through document.write is equivalent to the tag added to the document, because it operates on the document stream (so using document.write for loaded pages will automatically call the document.open, which will overwrite the original doc content). That is, under normal circumstances, link will block rendering and script will execute synchronously. However, this is not recommended, Chrome will already display a warning that this introduction may be prohibited in the future. If you add an async attribute to a script introduced in this way, Chrome will check whether it is of the same origin, which is not allowed for non-homologous async-scripts.

If you use innerHTML to introduce script tags, the JavaScript in them will not be executed. Of course, it can be handled manually with eval (), but it is not recommended. If you introduce link tags, I have experimented with it working in Chrome. In addition, outerHTML and insertAdjacentHTML () should have the same behavior, I did not experiment. These three should be used for text operations, that is, only use them to add text or normal HTML Elements.

Rearrangement and repaint

There will always be an initialized page layout accompanied by a drawing. (Unless you want your page to be blank:)) After that, every change in the information used to build the render tree will result in at least one of the following behaviors:

  1. Part of the render tree (or the entire render tree) needs to be reanalyzed and node sizes need to be recalculated. This is called ** rearrangement **. Note that there will be at least one rearrangement here - initializing the page layout.
  2. Some content on the screen needs to be updated due to changes in the geometric properties of the node or due to changes in the style, such as changing the background color of the element. Such an update is called redrawing.

Rearrangements and repaints are expensive, they break the User Experience and make UI presentation very slow.

Under what circumstances will rearrangement and redrawing be triggered?

Any changes to the information used to build the render tree will result in a rearrangement or repaint.

  • Add, delete, update DOM nodes
  • Hide a DOM node via display: none - triggers rearrangement and repaint
  • Hide a DOM node via visibility: hidden - only triggers redraw because no geometry changes
    Move or animate DOM nodes in the page
  • Add a style sheet, adjust style properties
    User behavior, such as resizing windows, changing font size, or scrolling.

Reference link:

浏览器渲染过程

浏览器资源加载

https://juejin.im/entry/582f16fca22b9d006b7afd89