How does browser work step by step [latest] — optimization in the loading stage (part 4)
What is the point of knowing how a browser works? We can improve performance with confidence.
When using a browser, usually, we open a URL, interact with the page, and close the tab when getting what we need.
These are three stages during the entire interaction between a user and a browser:
- Loading stage — it starts when we enter a URL.
- Interaction stage — it begins when we can browse, click, and interact with the page.
- Closing stage — it starts when we click the close button on a tab.
The web front-end optimization focus on the loading and interaction stages.
From the navigation to rendering phases, the critical optimization point is the DOM construction phase. Many factors could block the HTML parsing and prolong the entire rendering phase. When it happens, we, as a user, have to stare at a white screen for a while.
DOM construction blocking
We focused on the rendering phases and skipped some details of the HTML parsing in the last post.
HTML document contains more than HTML, including CSS styles and JavaScript files. Both could block DOM construction and reduce web performance.
How JavaScript blocks the DOM construction?
Let’s start with a simple example, an inline JavaScript.
In the example, the script replaces the inner text of an element. It modifies the DOM tree.
HTML parser is responsible to “translate” the HTML document. When seeing the JavaScript script, the HTML stops parsing the DOM and executes it immediately. When the execution completes, the HTML parser continues parsing the rest of the HTML document.
What if it is a JavaScript file linked to the script tag?
When seeing the linked script file, again, the HTML parser stops DOM tree construction. Meanwhile, the renderer process communicates to the network process, asking to download the JavaScript file from the server. When the network process delivers the data, the renderer process executes the script before continuing to parsing the HTML file.
The download process increases the time to construct the DOM tree on top of the time the browser executes JavaScript.
How CSS blocks the DOM construction?
CSS along doesn’t block the DOM construction. It does when combining with JavaScript.
In this case, a CSS style file is referenced in the HTML, and JavaScript modifies the style in the “styles.css” file.
The renderer process needs to have computed style ready before executing the JavaScript to modify the styles. Therefore, the HTML parser cannot continue until the CSS file is parsed, and the JavaScript file execution is completed.
When developing a website, it is inevitable to have linked files in our HTML document.
To accelerate the process, a preload scanner quickly scans the document data concurrently while building the DOM tree. If the preload scanner finds any linked files, for example, CSS and JavaScript files, it creates an IPC connection to the network process and requests the data from the server.
When does the renderer process resume the DOM structuring? It depends on the file taking the most extended length of download time.
Let’s say two files need to be downloaded. One file takes 1 second, and the other takes 3 seconds. The total is 3 seconds.
Optimization in the loading stage is about reducing the download time
When building the DOM tree, The most time-consuming parts are downloading linked files and executing JavaScript.
Key indicator — round-trip delay time (RTD)
When it comes to optimization, we need a key indicator to measure it, so we know if the solution works.
Round-trip delay time (RTD) or round-trip time (RTT) is a general term in telecommunications measuring the length of time it takes to send and receive a signal.
In our context, the time measurement starts when the network process sends a request to a server and ends when it receives the complete confirmation from the server. RTD is the total length of the time it takes to complete this process.
Because of the features of TCP, the data is sent in chunks. Take a CSS file, for example, the size is 0.1M. The size of each chunked data pack sent through HTTP, usually, is around 14KB. A 0.1M file is divided into 8 packs. We can say the CSS file takes 8 RTD to complete.
How about downloading two files? One CSS file is 9KB, so it takes 1 RTD to download. Another JavaScript file is 15KB taking 2 RTD to complete downloading. Since the download happens parallel, the total time is 2 RTD.
The calculation here is not entirely accurate because we ignore the TCP connection time and the server response time, but you get the idea.
With RTD in mind, now we can talk about the optimization:
- Reduce the number of key resources
- Minimize the size of key resources
Reduce the number of key resources
What are the key resources? Any CSS and JavaScript files are required when loading a page. Without them, your website is broken.
To reduce the linked files, we can move essential CSS and JavaScript data directly in the HTML file to avoid the download process.
If some linked JavaScript files don’t morph the DOM tree and styles, mark them with “defer” and/or “async,” so they don’t block the DOM construction.
A deferred script executes when the DOM is ready but before the “DOMContentLoaded” event. An async script is independent of other scripts and events. It runs as soon as it is available.
Some believe that it helps to separate a large CSS file into smaller ones based on media queries. It is not entirely true. A stylesheet with a media query attached to its <link> tag will still download even if the query returns false. It is just the content doesn’t apply the styles. Therefore, it doesn’t reduce the download requests.
Reduce the size of key resources
Smaller file size means fewer RTD. We can achieve it by compressing CSS and JavaScript files. Moreover, most compression tools remove the comments in the data, which helps reduce the file size.