One, foreword
What happens when the user enters a URL and the page is rendered?
Let’s review an article I wrote earlier, which mainly analyzes the process of the browser from loading ULR to returning resources to the server. If you are not familiar with this article, you can check it out (added more details).
When the browser makes a request and the server returns the resource, what does the browser do to turn the bytes into beautiful pages?
Aiming at this problem, need to do some in-depth study of the working principle of the browser, can clearly know the browser during this process, do what, can help us on the front end development or front end performance optimization, aiming at some point take different approaches to optimization, not only can recite to reduce HTTP requests, merger background, etc.
As we saw in the previous article, the browser requests network resources through a web process, which then “pipes” the web process and the renderer process into a message queue for processing by the renderer thread.
Two, the renderer process under the various threads
In the process of modern browsers is a multi-process architecture, which contains multiple threads, and handle HTML parsing and page rendering mainly occurs in the process of rendering, is we often say the browser kernel, rendering process mainly includes the GUI rendering threads, thread js engine threads, trigger events, timing trigger thread, synthetic thread, IO thread, etc
1. Render threads
The rendering thread is mainly responsible for rendering the page, parsing HTML, CSS, building layout trees, drawing layers and other operations
2. JS engine threads
JS engine thread is the interpreter used by the browser to execute JS, and a common implementation is V8 engine.
The JS engine thread and the rendering thread are mutually exclusive, that is, only one thread can be executing at a time.
This is because JS can add, delete, and change DOM nodes, so if JS modifies the DOM during rendering, it will repeatedly render.
So the JS engine is designed to be mutually exclusive, and while the JS engine is working, the rendering thread hangs and waits,
This leads to a problem we often encounter when js takes too long to execute, resulting in page stalling.
The event triggers the thread
We know that JS is an event-driven language that is single-threaded and executed asynchronously. The main processing of browser events, such as click events, move events, and then put the event into the end of the task queue for the JS engine to execute.
4, timing trigger thread
Mainly responsible for dealing with the timer in JS, because the JS engine is single thread, there may be blocking, so another thread is responsible for ensuring the accuracy of the timer.
Of course, we usually execute the timed event through the callback function, and the callback event will be added to the end of the task queue for execution. Therefore, if the JS engine is blocked, the specific execution time will be different.
5. Asynchronous request threads
When there is an XMLHttpRequest request, a new thread will send the request. When the return status changes, the callback event will be triggered, and the event will be put into the task queue for the JS engine to execute.
When the render thread takes the returned resource, the following process takes place. Let’s go through the process one by one
- The DOM parsing
- Byte stream token parsing
- Conversion of Token
- The DOM tree to build
- CSSOM parsing
- CSS token
- CSS formatting
- CSSOM build
- Layout of the tree
- DOM and CSSOM compute the layout tree
- Calculate the coordinates of DOM nodes and build the layout tree
- The layer tree
- Build a layer tree from the layout tree
- Draw lists and compose
- The rendering engine generates a list of draws from the layer tree, which it hands to the compositing thread
- The composition thread will draw a list to generate a graph block
- rasterizer
- Perform rasterization operation, synthesize bitmap of graph block and put it into rasterization thread pool
- Generate bitmaps, preferably those near the viewport
- According to
- It is then handed to the browser process and drawn into memory by the browser component for display
Build a DOM tree
The Performance panel of the browser developer tool records the tasks performed by the browser during the page loading process. You can clearly see that there is a task of parsing HTML, loading events, parsing and compiling JS.
In fact, there are a lot of tasks behind, but too many screenshots can not display information, screenshots of part, you can test.
In this step, the rendering thread will get the return header if the header contains the identity content_type: The HTML module parser of the rendering engine generates corresponding tokens through word parsing, namely tags
and
, and then pushes them into the stack it maintains and generates corresponding Node nodes. The DOM tree is built by constantly comparing the start node and the end node.
In the process of word parsing, if style and script reference files are found, the browser will open another thread for pre-download. Once the DOM tree is built, start parsing the pre-downloaded CSS.
During DOM parsing, if there is a JS script, the rendering thread will stop working and wait for the JS engine to execute, so referencing JS in the document header will cause page rendering to stall.
The top one is the printed DOM structure, which makes it possible to manipulate the DOM with JS.
Build a styleSheet
This step mainly happens: CSS parsing, CSS standardization, styleSheets Building (CSSOM)
CSS comes from four main sources:
- 1. Inline style
- 2, style tag embedded
- 3, Link introduction
- 4. Js introduction
In the process of parsing the DOM, the rendering engine will standardize the CSS and add it to the StyleSheetList, so that we can use the Console to print out the document. StyleSheets
CSS normalization is the normalization of syntax that browsers don’t recognize into something that they recognize. Such as
.demo {
font-size: 2em;
color: #000;
}
Copy the code
Converted into
.demo {
font-size: 28px;
color: rgb(0, 0, 0);
}
Copy the code
5. Layout the tree, calculate the style and Node coordinates
With the DOM tree and StyleSheetss, you are ready to build the layout tree. Hidden and invisible elements are not added to the layout tree. This process involves calculating the layout tree and rendering the layout tree.
We can see how each node evaluates in Elements.
Along the way, we discovered that we needed DOM and CSS stylesheets (known here as CSSOM) to build the layout tree.
If the CSS takes too long to download and CSSOM does not download or parse, the render thread will stop and wait for the CSS to process.
So if the CSS file is large or the network is poor, the final rendering time of the page will increase.
If JS code is executed during DOM loading and CSS is included in the JS, the rendering thread will also wait for the CSS to download, which also affects rendering time.
Layer tree
Once the layout tree is built, the rendering engine builds the layer tree from the layout tree without drawing.
Just like photoshop, each image is covered by several layers, and the final image is displayed. Layer tree is like this, processing the page into layers, each node has its own level, if not, it belongs to the parent node.
In the Browser Layers bar, you can see how the browser layers look
Click on the drawing list below and drag the drawing steps to recreate the drawing process
Common styles that can cause layering are z-index, clipping of DIV content that is larger than the width or appearing scroll bars,Fix,3D render, etc
Synthesize drawing list and raster operation
Once the layer tree is built, the rendering engine converts the layers into a draw list, as shown in the image above, which has only draw instructions.
The rendering engine then passes the drawing list to the compositing thread, which then draws the drawing list into blocks and performs rasterization, that is, the large page is divided into 256*256 or 512*512 sizes, and then generates a bitmap that prioritizes the visible areas of the page, which is also optimized by the browser for rendering.
The rendering engine maintains a pool of rasterized threads and, once rasterized, passes the drawing instructions to the browser process. If GUI acceleration is used for this step, subsequent operations will also be performed in the GUI process, which will not affect the rendering process and improve the rendering speed.
Eight, to draw
After the composite thread submits the instructions for drawing bitmaps to the browser process, the browser process calls its VIz components to draw them into memory according to the instructions and display them on the page.
So the whole process is complete.
9. Rearrangement and redrawing
Rearrangement and redrawing is one of the most common questions asked in interviews. If you do a lot of animation in your development, knowing this can help you optimize the animation.
Rearrangement, when the geometry of a page element changes, causes the page to recalculate the DOM tree, which then triggers a series of subsequent operations.
Redraw, when the color and other properties of the page change, only recalculates the style and then performs compositing operations, eliminating the DOM tree calculation process and reducing the pressure on the rendering engine.
Of course, wouldn’t it be faster if your changes didn’t trigger either a rearrangement or a redraw?
Right, so CSS animation implementations can use transform, which will only be processed during the compositing thread phase. If GUI acceleration is used, it will not affect the main process and render faster.
Here are some ways to reduce rearranging and redrawing:
- Use class to batch styles rather than frequently manipulating styles
- Avoid table layouts
- Using the framework, the framework uses the virtual DOM and uses algorithms to reduce the frequency of DOM manipulation
- Use transform to handle animations and so on
3. Optimization method
- Working principle and practice of browser