preface

It is very important for a front-end developer to improve the performance aspect of the website, which can better improve the user experience.

Introduction to The Browser

The main function of the browser can be summed up in a single sentence: to convert the URL entered by the user into a visual image.

The browser kernel (rendering engine)

Rendering engine, responsible for interpreting the syntax of the web page (such as HTML, JavaScript) and rendering the web page. Therefore, the so-called browser kernel is the rendering engine used by the browser. The rendering engine determines how the browser displays the content of the web page and the formatting information of the page. Different browser kernels interpret the syntax of the web page differently, so the same page may render differently in different browsers with different kernels, which is why web writers need to test the page display in different browsers.

Processes and threads

Process: The execution of a program, which occupies a unique piece of memory, is the basic unit of the operating system.

  1. A process has at least one running thread: the main thread. The process is automatically created after it starts.
  2. A process can also run multiple threads at the same time, the program is multithreaded.
  3. Data within a process can be shared by multiple threads. Data between multiple processes cannot be shared directly.

Thread: a unit of independent execution within a building. It is the smallest unit of CPU scheduling and the basic unit of program execution.

Thread pool: A container that holds multiple thread objects for reuse.

Modern browsers: multi-process, multi-threaded model

  1. In the past: when you open multiple pages via a browser, if one of the page does not respond or collapse, so will be followed by more bad things, you can’t open all the pages and response, the most let a person can’t stand is that some of these pages also contains some information not to send, not save
  2. Browser vendors solution: Adopt multi-process model, which can bring benefits: when a third-party plug-in crashes, the stability and security of the entire browser will not be affected.
  3. What processes the browser has
    1. Browser process: the main process of the Browser, responsible for the display of the Browser page, and the management of each page. The ancestor of all other types of processes in the browser, responsible for the creation and destruction of other processes, one and only.
    2. The number of Render processes is not necessarily equal to the number of pages you open
    3. Various plug-in processes
    4. GPU: Browsers on mobile devices may be different. Android does not support plugins so there is no plugin process, GPU evolved into a county of Broser process

The main purpose of multithreading is to keep the user interface highly responsive. For example, to prevent the UI thread of the Browser process from being blocked by other time-consuming operations (reading and writing local files), we put these operations into threading. In the render process, in order not to let other operations prevent the render thread from executing at a high speed, we usually pipe the render process, taking advantage of the multi-core computer to have different stages of rendering executed in different threads.

How browsers render

The main module

A rendering engine mainly includes: HTML parser, CSS parser, JavaScript engine, layout layout module, drawing module

  • HTML parser: A parser that parses HTML documents, interpreting the HTML as a DOM tree,
  • CSS parser: It computes style information for various elements of the DOM and provides the infrastructure for layout.
  • JavaScript engine: The content of a web page can be modified using JavaScript code, as well as CSS information. JavaScript engine can interpret JavaScript code and modify the content and style information of a web page through DOM interface and CSS tree interface
  • Layout: After the DOM is created, WebKit needs to combine elements and objects with style information, calculate their size and location, and create an internal presentation model that expresses all this information
  • Paint: use the graphics library to calculate the layout of each web page node address and image results

Rendering process

The entire process of the browser rendering the page: the browser parses the document from top to bottom.

  1. When an HTML tag is encountered, the HTML parser is called to parse the corresponding token (a token is the serialization of a tag text) and build a DOM tree (a chunk of memory that holds the token).
  2. Encountering a style/link tag invokes a CSS parser to process the CSS tag and build a CSS style tree.
  3. Encountering a script calls the JavaScript parser to handle the script dart flag, bind events, modify the DOM /CSS tree, etc.
  4. Combine the DOM and CSS trees into one render tree.
  5. Render against the render tree to calculate geometric information on each node (this process depends on the graphics library).
  6. Acknowledgement of each node to the screen.

Style tag style rendering

  1. Styles in the style tag are parsed by the HTML parser

  2. Browsers load resources asynchronously

  3. The page style tag is written in a style that is parsed asynchronously

  4. The styles that link comes in are parsed by the CSS parser, and are parsed synchronously

  5. The CSS parser blocks the rendering of the page.

  6. Using link to introduce styles is recommended

Verify CSS and JS blocking

This is the file directory

This is a file written in Node

const http = require("http");
const fs = require("fs");
http.createServer((req,res) = >{ 
    if(req.url === '/index.html'){
        fs.readFile("./staitc/html/index.html",(err,data)=>{
            if(err){
                res.end("Error reading file")}else{
                res.end(data)
            }
        })
    }
    if(req.url === '/css/common.css'){
        fs.readFile("./staitc/css/common.css",(err,data)=>{
            if(err){
                res.end("Error reading file")}else{
                res.end(data)
            }
        })
    }
}).listen(3000)
Copy the code

index.html


      
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
    <style>
        div {
            width: 400px;
            height: 400px;
            background: red;
        }
    </style>
    <link rel="stylesheet" href="/css/common.css">
</head>

<body>
    <div></div>
</body>

</html>
Copy the code

common.css

div {
    width: 200px;
    height: 200px;
    background: blue;
}
Copy the code

When we force the refresh N times, we get common.css style each time, which I won’t describe here

Verifying CSS blocking

Above we said that link comes in with a style that prevents the page from rendering. So why don’t we see that now?

Reasons: 1. The style we link in is very simple. 2.

To make it more intuitive to verify that CSS blocks page rendering. We delay the common.css file by 3000 milliseconds.

Modify the index.js file

 if (req.url === '/css/common.css') {
        fs.readFile("./staitc/css/common.css", (err, data) => {
            if (err) {
                res.end("Error reading file")}else {
                setTimeout(() => {
                    res.end(data)
                }, 3000)
            }
        })
    }
Copy the code

After save, through node index. Js, restart the server, then open the page http://localhost:3000/index.html,

At this point, we realized that the browser was going around in circles and the page was not updated until 3 seconds later when the page was rendered.

If CSS does not block the rendering of the page, the first selection of render will execute the style in index.html, and then render the style in common.css when it returns.

This proves that the CSS in link blocks the rendering of the page.

Link incoming CSS does not block page parsing

Now let’s modify index.html

<! DOCTYPE html> <html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
    <style>
        div {
            width: 400px;
            height: 400px;
            background: red;
        }
    </style>
   
    <script>
        setTimeout(() => {
            const div = document.querySelector("div")
            console.log(div)
        })
    </script>
     <link rel="stylesheet" href="/css/common.css">
</head>

<body>
    <div></div> 
</body> 
</html>
Copy the code

Then visit http://localhost:3000/index.html again, we are surprised to find the script statements execute and output properly

You can see that the DOM tree has been parsed at least to the div, and the CSS has not been loaded yet, which means that the CSS does not block the parsing of the page.

Will link’s incoming CSS block subsequent JS execution?

Now let’s modify the structure of index.html again


      
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
    <style>
        div {
            width: 400px;
            height: 400px;
            background: red;
        }
    </style>

    <script>
        console.log('before css')
        var startDate = new Date(a)</script>
    <link rel="stylesheet" href="/css/common.css">
</head>

<body>
    <div></div>
    <script>
        var endDate = new Date(a)console.log('after css')
        console.log('Past' + (endDate - startDate) + 'ms')
    </script>
</body>

</html>
Copy the code

Then visit http://localhost:3000/index.html again, we are surprised to find the script statements execute and output properly

As you can see from the figure above, the JS code before the CSS loading statement is executed first, but the code after the CSS loading statement is not executed until after the CSS loading is complete. This means that CSS loading blocks subsequent JS statements

This proves that the CSS in link blocks the execution of subsequent JS statements

Validate JS blocking

Js blocks page parsing

Js blocks page rendering

CSS layer

When a browser renders a page, it layers the page in layers, large and small, with one or more nodes on each layer. When rendering the DOM, what the browser actually does is:

  1. Get DOM split into layers
  2. Compute the style result for each layer node —- (Recalculate style Recalculate)
  3. Generate graphics and locations for each node —- (Layout rearrangement, reflux)
  4. Draw and fill each node into the layer bitmap — (Paint redraw)
  5. The layer is uploaded to the GPU as a texture
  6. Combine multiple layers onto the page to generate the final screen image. — (Composite Layers)

Layer creation conditions

Chrome creates layers for any situation

  1. Have 3D transform properties
  2. Video nodes that use accelerated video decoding
  3. Canvas node
  4. CSS animation node
  5. The element that has the CSS accelerated property

redraw

Redraw is the behavior of the browser triggered by changes in the appearance of an element, such as changing the properties of outline or background color. The browser rerenders the elements according to their new attributes, and relayouts are not necessarily associated with rearrangement.

It’s important to note that repainting is done on a layer basis, so if one element of a layer needs to be redrawn not the whole layer needs to be redrawn.

For example, if you have a layer with a lot of nodes, and you have a GIF, and each frame of the GIF, you redraw all the other nodes of the layer, and then you get the final slaughter, So this requires a special way to force the GIF to be on its own layer (tanslateZ(0) or tanslate3D(0,0,0)). Same goes for CSS animations (fortunately, in most cases browsers will create layers for the CSS3 animation node).

Rearrangement (reflux)

Render objects do not contain location and size information when they are created and added to the render tree. The process of calculating these values is called layout or rearrangement

Redrawing doesn’t have to be rearranged. For example, changing the color of a web element will only trigger redrawing, not rearrangement, because the layout hasn’t changed. But rearrangement always leads to redrawing. Changing the position of an element, for example, triggers both rearrangement and redrawing because the layout has changed.

Optimized redraw reflux

  1. Use TansForm instead of top and left when changing the position of an element
  2. When modifying styles in batches: useel.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px; '
  3. Leveraging document fragments
  4. Take the DOM offline before modifying it: Since elements with the Display attribute node are not in the rendering tree, operations on hidden elements do not cause rearrangements of other elements.
  5. Create a new layer for the animation element to increase the z-index of the animation element
  6. Avoid triggering synchronous layout events
  7. CSS Hardware Acceleration