Understanding the crucial steps involved in a browser’s construction and rendering of a webpage is key to enhancing web performance.
The essence of optimizing web performance lies in grasping the intermediate steps from receiving HTML, CSS, and JavaScript to transforming these into rendered pixels. This process is known as the “critical rendering path”.
Main focus: browser-based processes
This discussion will concentrate on the browser’s local operations, excluding network flow effects on web performance. Our article get better Network Performance by monitoring Latency and Jitter delves into network-related aspects in more detail.
We will delve into the various steps of building and rendering a webpage and explore key components for optimal web performance.
Webpage rendering principles
A browser requests a webpage via an HTTP(S) GET request. A successful request leads to a server response with HTML page data.
The browser then undertakes these steps:
- DOM construction
- CSSOM construction
- Render tree building
- Layout formation
- Painting
Before painting on the screen, the browser performs several crucial tasks. Let’s dive deeper into these processes.
DOM building
“Document Object Model” (DOM) outlines the webpage’s structure based on HTML markups. The browser transforms raw HTML bytes into characters, tokens, and finally objects, which are then linked to form the DOM tree.
CSSOM building
“Cascading Style Sheets” (CSS) determine HTML element styling. CSS is converted into a CSSOM tree, similar to the DOM process, involving character, token, and node transformations.
Render tree construction
The separate CSSOM and DOM trees merge to form the render tree, used for layout computation and pixel rendering on the screen.
Layout and painting
The layout phase calculates the position and size of elements, followed by the painting stage where each node is converted into screen pixels.
Recap and optimization
Quick recap: HTML and CSS processing leads to DOM and CSSOM trees, which combine into a render tree for layout and painting. Minimizing the time spent in these steps is crucial for optimizing the critical rendering path. In summary:
- Process HTML markups and build the DOM tree
- Process CSS markups and build the CSSOM tree
- Combine the DOM and CSSOM into a render tree
- Run layout on the render tree to compute geometry of each node
- Paint the individual nodes to the screen
Challenges and solutions
The essential rendering process hinges on the utilization of both the Document Object Model (DOM) and the CSS Object Model (CSSOM) to form the render tree. Put differently, the browser needs to fully parse the HTML content and fetch the CSS styles before it can commence rendering anything visible on the screen. HTML and CSS are considered as “render-blocking” resources. When a webpage is kept at its simplest, it consists of an HTML file that lacks any CSS or additional resources, such as JavaScript.
The entire sequence of actions, from requesting the webpage to displaying the outcome on the screen, can be depicted as follows:
- The browser initiates the process by sending an HTTP(S) GET request to the web server over the network.
- While awaiting the web server’s response, the browser remains in an idle state.
- Once the browser receives the HTML file, it proceeds to construct the DOM, as previously explained.
- After the DOM is fully assembled, the browser can begin rendering the page.
Seems quite straightforward, doesn’t it? Now, let’s explore what occurs when a CSS file comes into play.
CSS
By default, CSS is regarded as a resource that blocks rendering, meaning that the browser refrains from rendering any processed content until the CSS Object Model (CSSOM) has been constructed. Therefore, it is crucial to acquire the CSS file as swiftly as possible to minimize any additional rendering delays.
In this scenario, the process unfolds as follows:
- The browser initiates the process by sending a GET request to the web server over the network.
- While awaiting the web server’s response, the browser remains in an idle state.
- Upon receiving the HTML file, the browser proceeds to construct the Document Object Model (DOM). However, in this case, there’s a tag that references an external CSS file.
- The browser continues with DOM construction but now also needs to create a CSS Object Model (CSSOM). To achieve this, it sends another network request to retrieve the CSS file.
- During this period, the DOM is ready, but the browser must complete the construction of the CSSOM. Consequently, the browser remains idle.
- Once the CSSOM is fully constructed, the browser can assemble the render tree and, at last, render the page.
This sequence underscores the importance of obtaining the CSS file as swiftly as possible to minimize any additional rendering delays, as CSS is treated as a render-blocking resource by default.
Blocking JavaScript
When the HTML parser encounters a <script> tag, it momentarily halts the process of constructing the DOM and transfers control to the JavaScript engine. After the JavaScript engine completes its execution, the browser resumes DOM construction from where it paused.
It’s evident that delaying the DOM construction inherently results in a delay in the rendering process.
- The browser initiates the process by sending a GET request to the web server over the network.
- While waiting for the web server’s response, the browser remains idle.
- Upon receiving the HTML file, the browser proceeds with DOM construction. However, in this case, there is a <link> tag referencing a CSS file and a <script> tag referring to a JS file.
- The browser cannot continue DOM construction and must first fetch and execute the JS file. Concurrently, it also fetches the CSS file to construct the CSSOM.
- After receiving the CSS file, the browser constructs the CSSOM.
- Once the JS file is received, the browser executes it and waits for the result before continuing to parse the HTML file and construct the DOM.
- Once the DOM is fully constructed, the browser can create the render tree and, finally, render the page.
Non-blocking JavaScript
In conclusion, for optimal performance, it is advisable to minimize the impact of executing JavaScript during the HTML parsing process (DOM construction).
To achieve this, you can:
- Remove any unnecessary JavaScript from the critical rendering path.
- Execute your JavaScript in “async” mode.
- The browser initiates the process by sending a GET request to the web server over the network.
- While awaiting the web server’s response, the browser remains in an idle state.
- Upon receiving the HTML file, the browser starts building the DOM. This time, however, there is a <link> tag referring to a CSS file and a <script> tag pointing to a JS file, both in ‘async’ mode.
- As the JavaScript is specified in ‘async’ mode, the browser can continue with DOM construction. While constructing it, it sends network requests to fetch the CSS file and the JS file.
- Once the CSS file is received, the browser constructs the CSSOM.
- When the JS file arrives, the browser executes it and waits for the result before rendering the page.
A Possible Challenge: What if the browser hasn’t completed the download and construction of the CSSOM when it’s ready to execute the script? The answer is straightforward but not favorable for performance: the browser delays the script execution and DOM construction until it has finished downloading and constructing the CSSOM.
In summary, JavaScript introduces additional dependencies among the DOM, CSSOM, and JavaScript execution, potentially causing significant delays in processing and rendering the page on the screen.
To enhance performance:
- Eliminate unnecessary JavaScript
- Use async JavaScript execution
check our article to get better web performance by using Javascript “defer” and “async”