Performance Optimization - More Efficient Data Rendering

Foreword: The central idea is to make the requested resources get a faster response, such as compressing resources, reducing the size of data, caching data to reduce the number of requests, http/2 makes network transmission faster, etc. Let us come to See how the browser parses these data and finally renders them on the screen? What other points can be optimized when the amount of data remains unchanged?

How the browser renders, starting from entering a path address

When the browser obtains an html file, it will be loaded "top-down", and parsed and rendered during the loading process.
Steps: Build DOM and CSSOM -> Build render tree -> Layout render tree -> Draw render tree

1. Parse HTML into a DOM (Document Object Model)

The browser will parse the tags in the html file, such as: <html>, </body>, <p>, and mark these tags. After encountering the tags, the browser uses the token generator to start generating tokens. For example, <p>hello</p>such a text tag will generate: StartTag:p, hello, EndTag:p Such 3 tokens, and then generate corresponding nodes (nodes) to form DOM, which is the Document Object Model (DOM for short)) ;
![Insert picture description here](https://img- blog.csdnimg.cn/fe932a8694dd40bc927fec0f0a07cd34.png
insert image description here
insert image description here

2. Parse CSS into CSSOM (Cascading Style Sheet Object Model)

When a <link> tag is encountered in html parsing, the corresponding CSS file will be requested, and it will be parsed when the CSS file is in place (if an inline <style

When it is directly parsed), this parsing process can be carried out at the same time as building the DOM. In fact, the process of building a css tree is similar to that of a dom tree. It also went through the process of marking, generating tokens and nodes, but the identification mark rules here are different from dom, because css has an operation method of inheriting attributes, and the parent part attribute style will be inherited by the child style, such as font font-size ,
font-weight, font-style,
line-height, etc., and some default styles, as shown by the arrow in the figure below, is the default style, and the red box is the inherited style.

insert image description here

3. Construct the Rendering Tree.

According to the DOM tree, each visible node is traversed, and for each visible node, a matching style is found on the CSSOM and applied to generate a Rendering Tree.
At this time, rendering the tree is not equivalent to building the DOM tree, because if the invisible (display:none) attribute is encountered, the element and its children will be skipped. In addition, the head of html does not contain any visible information, so this part of the content will be quickly removed;
insert image description here

4. Layout

With Render Tree, the browser can already know which nodes are in the web page, the CSS definitions of each node, and their affiliation. The next step is to calculate the position and size of each node on the screen, this operation is called Layout.

5. Draw

That is, it traverses the render tree and uses the UI backend layer to draw each node and display it on the screen in pixels.
What needs to be noted here is:
1. Not all the data has been loaded, but a part is displayed first, and then another part is displayed.
2. Although it is loaded from top to bottom, it is not necessary to wait for the upper content to be displayed before displaying the lower content, but whoever parses it faster will render it faster.
3. CSS loading will not block the loading of DOM, but it will block the rendering of DOM. Although DOM and CSSOM are usually built in parallel, Render Tree is dependent on DOM Tree and CSSOM Tree, so he must wait until CSSOM Tree is built, that is, CSS resources are loaded, before rendering can start.
If external styles are referenced, you need to wait for all these styles to be loaded before starting to build CSSOM. Because the css file contains a large number of styles, the later styles will cover the previous styles. If we build the CSSDOM in advance, we may get wrong results.
4. JS files not only block the construction of DOM, but also block the construction of DOM in CSSOM; when constructing DOM, if the HTML parser encounters JavaScript, it will suspend the construction of DOM and hand over control to the JavaScript engine, etc. After the JavaScript engine finishes running, the browser resumes DOM construction from where it left off.
This is because JavaScript can not only change the DOM, it can also change the style, that is, it can change the CSSOM. Because an incomplete CSSOM cannot be used, if JavaScript wants to access the CSSOM and change it, it must be able to get the complete CSSOM when executing JavaScript. That is, in this case, the browser will first download and build the CSSOM, then execute the JavaScript, and finally continue to build the DOM.
Therefore, if we want to render the first screen faster, we should not load JS files on the first screen, which is why it is recommended to place the script tag at the bottom of the body tag. Of course, at the moment, it does not mean that the script tag must be placed at the bottom, because you can add defer (delayed execution) or async (asynchronous download) attributes to the script tag;

Critical Rendering Path Optimization

The critical rendering path is the series of steps a browser
goes through to convert HTML, CSS, and JavaScript into pixel content that is rendered on the screen. That is the browser rendering process we just mentioned.

1. Put the data that can be parsed quickly in front, and put the data that is not easy to parse in the back

HTML semantic tags strengthen DOM parsing, because semantic tags are tags that can be parsed and recognized within the browser;
try not to use table layout. Because a small change may cause the entire table to be re-layouted, and the table is not loaded and rendered bit by bit, it is rendered after the entire load is loaded; some decorative elements can use pseudo-
elements appropriately to avoid adding meaningless page elements;

2. Let CSSOM not block the rendering of DOM

Not all CSS resources are so "critical" .

For example: some responsive CSS will only take effect when the screen width meets the conditions, and some CSS will only take effect when the page is printed. These CSS will not take effect when they do not meet the conditions, so why do we let the browser wait for CSS resources we don't need?
We can move the printing-related CSS to print.css, and then add the media query attribute print when we introduce CSS in HTML, the code is as follows:

The above code adds the media="print" attribute, so the above CSS resource is only used for printing. After adding the media query attribute, the browser will still download the resource, but if the condition is not met, it will no longer block rendering;

The method provided above is for those CSS resources that do not need to take effect. If the CSS resources need to take effect on the current page, but do not need to take effect when the first screen is rendered, then for faster first-screen rendering, we can also set these CSS become non-critical resources. It's just that we need some hacky ways to achieve this requirement:

<link href="style.css" rel="stylesheet" media="print" onload="this.media='all'">

The above code first sets the media query attribute to print, and sets the resource to a non-blocking resource. Then after the resource is loaded, set the media query attribute to all to make it take effect immediately on the current page.

There are similar solutions, the code is as follows:

<link rel="preload" href="style.css" as="style" onload="this.rel='stylesheet'">
<link rel="alternate stylesheet" href="style.css" onload="this.rel='stylesheet'">

To sum up, the CSS needed for the first screen rendering is embedded into the head tag through the style tag, and the rest of the CSS resources are loaded in an asynchronous way and non-blocking. After optimization, you can check whether the time point of FP (first drawing) is advanced.
image.png

3. Do not use the @import attribute as much as possible. The import attribute will be equivalent to writing css to the bottom of the document after the page is loaded, and loading multiple css files will be serially loaded, so this situation should be avoided.

4. CSS selectors are matched and searched from right to left. Too many node levels should be avoided, and sub-selectors should be used appropriately, such as .list>a>img

5. Asynchronous JavaScript

In order to avoid blocking, you can add async or defer attributes to the script tag. The execution of async is that it will be executed immediately after loading, instead of waiting for all the scripts to be loaded and executed in order like defer, you can listen to these two pictures below to compare their differences:

Blue: document parsed
Purple: script loaded
Yellow: script executed
Green: HTML document fully loaded and parsed

defer

Applicable if your script code depends on the DOM elements in the page (whether the document is parsed), or is depended on by other script files.
image.png

async

Applicable if your script doesn't care about the DOM elements in the page (whether the document is parsed or not), and it doesn't generate data that other scripts need.
image.png

6. Reduce the number of times JS operates DOM

Think of the DOM and JavaScript each as an island, connected by a toll bridge. - "High Performance JavaScript"

DOM is something in the rendering engine, and JS is something in the JS engine. When we use JS to manipulate DOM, it is essentially a "cross-border communication" between the JS engine and the rendering engine. The realization of this "cross-border communication" is not simple, it relies on the bridging interface as a "bridge".
image.png

There is a toll for crossing the "bridge" - the cost itself cannot be ignored. Every time we manipulate the DOM (whether to modify or just to access its value), we have to go through a "bridge". If you cross the "bridge" more times, you will have more obvious performance problems. Therefore, the suggestion of "reducing DOM operations" is not groundless.

1. The most common
operation of caching Dom objects is that Dom will first access Dom, especially for operations such as loop traversal, which may have relatively high event complexity. Then, the main node can be set before looping, and the Dom nodes that do not need to loop first. If it is obtained, it can be directly referenced in the loop without having to re-query.

image.png

2. Vue virtual node
Virtual Dom is a technology that js simulates the DOM tree and operates on the DOM tree. Virtual DOM is a pure js object (string object), so it will be efficient to operate on it.
Operate the virtual dom when the dom changes, compare the structure of the virtual dom with the original virtual dom through the dom diff algorithm, and finally repair the real dom structure in batches, avoiding frequent modification of dom as much as possible Frequent reflows and repaints.

Reduce reflow/repaint

Reflow (reflow): When the browser finds that a certain part has changed and affects the layout, we need to re-validate and calculate the Render Tree. Part or all of the Render Tree has changed - this is Reflow, or Layout.

Repaint: If you only change the background color, text color, etc. of an element, and do not affect the attributes of the surrounding or internal layout of the element, it will only cause the browser to redraw and redraw a certain part.

Therefore, it can be seen that rearranging takes more time than redrawing, and it affects performance more. So when writing code, try to avoid too much rearrangement.

The following actions cause a reflow or repaint:

  • Delete, add, or modify DOM element nodes.

  • When changing the size and position of an element, or using display:none, it will cause rearrangement; modifying CSS color or visibility:hidden, etc. will cause redrawing.

  • When modifying the default font of a web page. When resizing the window (the mobile terminal does not have this problem), or when scrolling. The content changes, (the user writes the content in the input box as well).

  • Activates pseudo-classes such as :hover.

1. Reduce DOM operations, such as changing the size, position, and display of elements. The class of css can be defined in advance, and then the className of DOM can be modified;

2. Use fixed or absolute position for animated HTML components, then modifying their CSS will not reflow.

3. Hide the element, modify it, and then display the element.

4. You can use the document fragment to create a subtree, and then copy it into the document. The document fragment is a lightweight document object. It is designed for tasks such as updating and moving nodes, and the document fragment also has One advantage is that when adding a document fragment to a node, what is added is the child node group of the document fragment, and it will not be added.

let fragment = document.createDocumentFragment();
appendNode(fragment, data);
ul.appendChild(fragment);

lazy loading (lazy loading)

1. Image lazy loading

The biggest impact on the page loading speed is the picture. An ordinary picture can reach a size of several M, while the code may only be tens of KB. When there are many pictures on the page, the loading speed of the page is slow, and the page is not loaded within a few seconds, and the user will lose patience.
In order to speed up the page loading speed, many times we need to not load the pictures that do not appear in the visible area on the page, and load them after scrolling to the visible area. Reference library: vue-lazyload

<img v-lazy="/static/img/1.png">

2. Routing lazy loading

Divide the components corresponding to different routes into different code blocks, and then load the corresponding components when the route is accessed, which can reduce the loading of invalid resources, significantly reduce the pressure and traffic of the server, and also reduce the burden on the browser .
Implementation: Combining Vue's asynchronous components and Webpack's code splitting function

const Foo = () => import('./Foo.vue')
router = new VueRouter({
    
     routes: [ {
    
     path: '/foo', component: Foo } ]})

(The picture materials are all from the Internet, and the infringement contact will be deleted immediately)

Guess you like

Origin blog.csdn.net/weixin_49549509/article/details/130280617