In front-end interviews, there is a classic interview question: describe the process from URL input to page rendering. This question examines the candidate’s ability and depth of knowledge. Today, we will talk about what optimization can be done in this process based on this question.

The process from entering the URL until the page loads

  • Do a DNS query first. If smart DNS resolution is performed in this step, the fastest IP address will be returned

  • The TCP handshake follows. The application layer sends data to the transport layer, where the TCP protocol specifies the port numbers of both ends and sends the data down to the network layer. The IP protocol at the network layer determines the IP address and indicates how to redirect the router during data transmission. The packet is then encapsulated into the data frame structure of the data link layer, and finally the physical layer transmission

  • After the TCP handshake is complete, the TLS handshake is performed, and data transmission begins

  • Before the data goes to the server, it may also pass through the load-balancing server, which distributes the request reasonably across multiple servers, assuming that the server responds with an HTML file

  • First of all, the browser is going to figure out what the status code is, if it’s 200 it’s going to keep parsing, if it’s 400 or 500 it’s going to get an error, if it’s 300 it’s going to get redirected, and it’s going to have a redirection counter, so it’s not going to get redirected too many times, but it’s going to get an error if it goes beyond that, okay

  • The browser starts parsing the file, if it’s in Gzip format it unzips it, and then it knows how to decode the file based on its encoding format, right

  • After decoding the file successfully, the rendering process will officially start. DOM tree will be built according to HTML first, and CSSOM tree will be built if CSS is available. If script tags are encountered, it will determine whether async or defer exists. The former will download and execute JS in parallel, while the latter will download the file first and wait for THE COMPLETION of HTML parsing before executing in sequence. If none of the above is present, the rendering process will be blocked until JS execution is complete. Encounter file download will go to download files, here if the use of HTTP 2.0 protocol will greatly improve the efficiency of multi-graph download.

  • The DOMContentLoaded event is triggered when the initial HTML is fully loaded and parsed

  • After the CSSOM and DOM trees are built, the Render tree is generated, which determines the layout, style, and many other aspects of the page elements

  • During the Render tree generation, the browser starts to invoke GPU rendering, compose layers, and display the content on the screen

HTTP optimization

Increase security: Use HTTPS instead of HTTP

HTTP,

HTTP is a hypertext transmission protocol, but in the process of information transmission, because communication uses plaintext, there may be the problem of information theft and tampering.

You can use secure HTTPS instead of HTTP

See Carlo Big Guy’s blog post detailing HTTPS

Reduce the number of requests: browser caching policy

When sending an HTTP request, the browser first checks for the presence of caches for the following four items in order

  • Memory Cache
  • Service Worker Cache
  • HTTP Cache
  • Push Cache

MemoryCache

A MemoryCache is a cache that exists in memory. In terms of priority, it is the first cache that the browser tries to hit. It is the fastest type of cache in terms of efficiency. Browsers are “frugal.” We found that Base64 images can almost always be stuffed into memory cache, which can be seen as a browser “self-preservation” to save on rendering costs. In addition, small JS and CSS files also have a greater chance to be written into memory – by contrast, large JS and CSS files do not have this treatment, memory resources are limited, they tend to be directly thrown into the disk.

Service Worker Cache

A Service Worker is a Javascript thread that is independent of the main thread. It is detached from the browser form and therefore cannot access the DOM directly. Such an independent personality prevents the “personal behavior” of Service workers from interfering with page performance. This “behind-the-scenes Worker” can help us achieve offline caching, message push, network proxy and other functions. The offline Cache we implement with Service workers is called the Service worker Cache.

HTTP Cache

It is divided into strong cache and negotiated cache. The strong cache has a higher priority. The negotiation cache is enabled only when the strong cache fails to be matched.

Push Cachae

Push Cache refers to the Cache that HTTP2 exists in the Server Push phase.

  • Push Cache is the last line of defense for caching. The browser will only ask for Push Cache if the Memory Cache, HTTP Cache, and Service Worker Cache all miss.
  • Push Cache is a Cache that exists during the session and is released when the session terminates.
  • Different pages can share the same Push Cache as long as they share the same HTTP2 connection.

For more on strong and negotiated caching in browsers, see Carry’s blog post on front-end static resource caching

For details on sevice Worker caching, see sevice Worker in Carry’s blog

Reduce the time spent on a single request: CDN

CDN has two core points, one is cache, one is back source.

“Caching” means that we copy a copy of the resource to the CDN server, and “back source” means that the CDN finds that it does not have the resource (usually the cached data expires) and turns to the root server (or its upper layer server) for the resource.

CDN is usually used to store static resources. Static resources refer to resources such as JS, CSS and images that do not need to be calculated by a business server. And “dynamic resources”, as the name implies, is the need for back-end real-time dynamic generation of resources, the more common is JSP, ASP or rely on the server render HTML pages.

What about “non-purely static resources”? It is an HTML page that requires the server to do additional calculations outside of the page. Specifically, before I open a site, the site needs to verify my identity through a number of means, such as permission authentication, to decide whether to present the HTML page to me. The HTML is static in this case, but it is coupled to the operations of the business server, and it is not appropriate for us to dump it on the CDN.

In addition, the domain name of THE CDN must be different from the domain name of the main business server. Otherwise, the Cookie under the same domain name runs everywhere, wasting the overhead of performance traffic. The CDN domain name is placed under a different domain name, which can perfectly avoid unnecessary cookies!

Rendering optimization

The browser rendering mechanism is generally divided into the following steps:

  • Process THE HTML and build the DOM tree.
  • Process CSS to build CSSOM trees
  • Merge DOM and CSSOM into a render tree.
  • According to the layout of the render tree, calculate the position of each node.
  • Call THE GPU to draw, synthesize the layer and display it on the screen

When rendering the DOM, what the browser actually does is

  • Take the DOM and split it into multiple layers
  • Compute the style result for each layer node (Recalculate style — Style recalculation)
  • Generate graphics and positions for each node (Layout – reflux and relayout)
  • Draw and fill each node into the layer bitmap (Paint Setup and Paint — Redraw)
  • The layer is uploaded to the GPU as a texture
  • Composite Layers onto a page to create a final screen image

Server side rendering

CSS Optimization Suggestions

CSS is a blocking resource. The browser does not render any of the processed content as it builds CSSOM. Even if the DOM is parsed, rendering is not OK as long as CSSOM is not OK. We put CSS in the head tag and enable CDN as soon as possible to optimize static resource loading speed. CSS selectors, such as #myList li {}, are matched from right to left.

  • Avoid wildcards and select only the elements you need.
  • Focus on attributes that can be implemented through inheritance to avoid repeated matching and repeated definitions.
  • Use label selectors less. If possible, use a class selector instead. #dataList li{} #dataList li{}
  • Rather than gilding the lily, ID and class selectors should not be held back by redundant label selectors. Error:.datalist# title Correct: #title
  • Reduce nesting. Descendant selectors have the highest overhead, so we should try to keep the depth of the selectors to a minimum (no more than three layers at most) and use classes to associate each tag element whenever possible.

Js block and Event Loop

The JS engine exists independently of the rendering engine. Our JS code is executed wherever it is inserted in the document. When the HTML parser encounters a Script tag, it pauses the rendering process and gives control to the JS engine.

The JS engine will execute the inline JS code directly, and the external JS file must first get the script, and then execute. Once the JS engine is finished running, the browser will return control to the rendering engine and continue to build CSSOM and DOM.

We put time-consuming JS operations at the end of the page and wait for the HTML and CSS to finish rendering before executing JS to prevent js from blocking the page rendering.

Js macro task and microtask

  • JS is divided into synchronous tasks and asynchronous tasks. The synchronous tasks are executed in the execution stack, and the callback of the asynchronous tasks is placed in the task queue to be executed when the execution stack is idle. SetTimeout and setInterval, XHR/fetch callback functions are asynchronous tasks.

  • The process of executing a task stack once is a macro task. After the result of one macro task is executed, the GUI rendering thread starts to render the page before the next macro task is executed.

  • A microtask is a task that the GUI thread executes after a macro task has completed. When a macro task completes, all microtasks generated during execution are completed before rendering. Promise, process. NextTick, etc., are microtasks

Proper arrangement of macro tasks, micro tasks and DOM operations can reduce invalid DOM operations as much as possible.

For more information on JS and Event Loop, please refer to the Bridge in the Cloud blog post for a comprehensive overview from multithreading to Event Loop

Refluxing and repainting

  • Backflow: When we make changes to the DOM that result in a change in the DOM’s geometry (such as changing the width or height of an element, or hiding an element), the browser recalculates the element’s geometry (which also affects the geometry and position of other elements), and then draws the calculated results. This process is called backflow (also known as rearrangement).

  • Redraw: When we make changes to the DOM that result in a style change without affecting its geometry (such as changing the color or background color), the browser doesn’t have to recalculate the element’s geometry and simply draw a new style for the element (skipping the backflow shown above). This process is called redrawing.

Redrawing does not necessarily lead to backflow, backflow does lead to redrawing. Reshoring does more work and costs more. In development, try to minimize the amount of backflow and redraw as much as possible at the code level.

Load balancing: Session replication