👩: The best time to plant a tree was ten years ago, the second best time is now! 🌝:2021-07-07 Another sunny day ~ 🙈: By my little HuiCopy the code

First let’s look at the concept of “CRP” 👇

英 文 原 文 : What is CRP, critical rendering path?

In each render link, understand its underlying operation mechanism, so as to do the relevant optimization

Let’s talk about threads & processes

Threads & Processes

When the browser opens a page, it opens up a process (program). There are many things to do in this page, so you need to allocate multiple threads to do these things. One thread can only do one thing at a time.

The popular version (speaking human language) : suppose there is a restaurant, the restaurant is a process, the hiring of many waiters, that one waiter is a thread, many waiters are multithreading. You can do a lot of things at onceCopy the code
  • Process size: The process contains one to more threads
  • Browsers are multithreaded
    • GUI rendering thread: Top-down rendering of the page (GPU rendering UI)
    • JS engine threads: Render and execute JS code
    • Time-triggered thread: During time binding, there is a thread that listens for the event to fire. Once the event is fired, this thread helps us tell the bound method to execute
    • Timer trigger thread: after the timer is set, a thread is allocated to monitor whether the time is up, and when the time is up, the corresponding method is notified to execute
    • Asynchronous HTTP request thread: Allocate a thread to fetch content “CSS/JS…” from the server.
    • WebWorker
    • .
  • JS is single-threaded: because the browser allocates only one thread, the “JS engine thread,” to render JS

When the browser gets the HTML page (code) from the server, it assigns a GUI rendering thread that renders the parsing code from top to bottom.

From the PERSPECTIVE of CSS

  • @1 If a tag such as (link/img) is encountered, allocate a new thread (HTTP request thread) to fetch the resource file, while the GUI continues rendering down regardless of whether the resource comes back, “without blocking GUI rendering”.

  • If @2 encounters (style), the GUI will continue rendering the code and parse the embedded style. “However, if the CSS resource request has been sent based on link before, then do not render at this time, need to wait until the CSS resource request comes back, render in order.”

  • @3 If @import ‘xxx. CSS ‘GUI stops rendering and assigns a new HTTP thread to fetch the resource file, it must wait until the resource file comes back, GUI will continue rendering and parse the acquired CSS code… “Blocking GUI rendering”

  • Optimization techniques:
    • Don’t use @import in your project if possible. “Exclude @import from less/sass because by the time the code compiles, the @import will be gone.”

    • If you have less CSS code, you can simply use inline to reduce the number of HTTP requests and make code render more timely, which is often done on mobile. The page opens faster the first time. But CSS code is more on the use of external chain “link”, so convenient code maintenance, also will not request HTML pages will take a long time.

The browser renders the page in four stages

  • The first step: Generate DOM TREE
    • Render and parse DOM structures and map out the relationships between nodes
    • When the “DOM TREE” is generated, a JS event is triggered: DOMContentLoaded

===> Optimization: Avoid deep DOM hierarchy nesting

  • The second step: Wait for all CSS resource requests to come back, according to the order of import, render CSS styles in turn, to ensure the order and priority of CSS rendering –> generate a “CSSOM TREE”

===> Optimization: We put link in the HEAD tag, send resource request before rendering DOM, so wait for DOM TREE generation, CSS has requested back, at this point directly render, let things do at the same time, can improve the speed of the first page rendering.

The number of concurrent HTTP requests to a page is 5-7 “restricted homologies”, and too many requests can block network channels… For many reasons, sending multiple HTTP requests is not as fast as sending only one request, so in this project, we need to merge all CSS resources into one file!! This eliminates the need to consider the rendering order of multiple resources

  • Step 3: Merge the generated “DOM TREE” and “CSSOM TREE” together to create the “RENDER TREE”.

    • The number of renders contains the style that each node should have when the browser renders the last time, “including: self-written style, inherited parent style, default style of the browser”. Window. GetComputedStyle (” element “)
  • Step 4: The browser starts rendering according to the RENDER TREE

    • @1 Layout: Calculates the position of each node in the viewport based on the viewport size of the browser
    • @2 Layering (document flow) : Separate from the document flow, build each layer of document flow, and plan how each layer draws “all the drawing steps are calculated”
    • @3 Painting: Start Painting the page according to the analyzed rules and finally render our page in the viewport of the browser

What happens when a script resource request is encountered?

  • GUI rendering is blocked by default when script is encountered

    • @1 sends an HTTP request to get the resource file, at which point GUI rendering stops
    • After the @2 resource is acquired, it is handed over to the JS engine thread to render and parse the JS
    • @3 JS parsing completed, GUI continues
    • Setting script to defer or async will not block GUI rendering
  • Script: Requesting resources and executing JS will hinder the GUI

  • Script async: Requests for resources do not prevent the GUI from “opening up a new HTTP thread to request, GUI rendering continues”. When the resource request comes back, it immediately renders and parses the JS

  • Script defer: The requested resource will not hinder the GUI, and no matter when the resource is retrieved, it will wait until the GUI is rendered and all JS resources (set to defer) are requested back. Finally, JS will be executed in the order of import.

  • The difference between Async and defer: Async doesn’t take into account JS dependencies and who asks back first executes first, but defer needs to wait for all resources to come back and the GUI to finish rendering before executing JS in the order of dependencies

Script is synchronous, and if you add defer and async it is asynchronous

Extract front-end performance optimization schemes

  • @1 To avoid deep nesting of HTML hierarchy, purpose: to speed up DOM TREE generation

  • @2 CSS selectors render from right to left, so CSS selectors avoid long prefixes. Purpose: To speed up CSSOM TREE generation (a{} vs. box a{})

  • @3 Preferred inline style purpose: To reduce the number of HTTP requests and speed up CSS rendering

  • Use @4 style overload cases, but to consolidate CSS resources into one CSS style file “Webpack can automatically pack” purpose: reduce HTTP requests and link does not hinder GUI rendering

  • @5 puts link in the header of the page. The purpose is to create a DOM TREE and request the resource file

  • @6 never use @import to “exclude sass/less”, because @import would block GUI rendering

  • We usually put script at the end of the page, and if we have to put script at the top, it is best to set defer or Async to prevent it from blocking the RENDERING of the GUI

  • @8 Real project, also need to consolidate all JS resources into a JS file, the purpose: to reduce HTTP requests

=====> All the optimizations are designed to make the page render faster and the white screen wait time shorter

Rearrangement (reflux)

  • The first time a page is rendered, it must go through a Layout arrangement that calculates the position of each node in the viewport
  • When “deleting or adding A DOM element, changing the position of a DOM element, changing the size of the element, changing the content… “When this happens, the browser recalculates the position of each point in the viewport (recalculates the Layout information). The Layout is rearranged, which costs a lot of performance.

redraw

  • The first rendering of the page must undergo a repainting, which is called Painting, rendering the page
  • When “changing some style of elements, such as text color, background color, background image, etc.”, these styles do not affect the layout structure of the page, we just need to redo the Painting, this is “redraw”.

Rearrangement inevitably causes repainting because it must go through the complete stage of Layout-> layering ->Painting

  • When we talk about DOM manipulation, we mostly refer to DOM rearrangement, so reducing DOM rearrangement is an important indicator of front-end performance optimization

  • The browser’s render queue mechanism

    • In the current context, if you encounter a DOM style modification operation, you do not immediately modify it, but first put it in the “render queue”, and then see if there is any further modification operation, if so, continue to put it in the queue… When the current context completes, all changes in the queue are processed at once, causing only one DOM rearrangement
    • If you encounter code that gets the style of an element, “refresh the render queue” means that any changes to the style in the current queue will be processed immediately.

How do you reduce DOM rearrangements?

  • 1. Give up direct DOM manipulation and use VUE/REACT and other frameworks to implement view rendering based on data drive. “Essence: The framework itself encapsulates DOM operations and internally optimizes DOM processing.”
  • 2, read and write separation: to modify the style and the code to obtain the style separate “centralized modification or centralized retrieval”
  • 3. Add or modify elements in batches: document fragments or template string splices
  • 4. Use CSS3 hardware acceleration (GPU acceleration)
    • Modifies the “transform/opacity… “This style does not cause a DOM rearrangement in the original document flow. Modifying the element’s transform will separate the element out of a document flow. The browser will simply recalculate the position and layout of the document flow and have no effect on the rest of the original document flow
    • In the same way, we later modify the style of elements, as much as possible, that are not part of the document flow, so that when we recalculate the layout information later, it is better to recalculate only the layer of the document flow than to recalculate the entire document flow
// This causes 10 rearrangements
for (let i = 0; i < 10; i++) {
  let span = document.createElement("span");
  span.innerHTML = i;
  document.body.appendChild(span);
} 
Copy the code
 // This causes a rearrangement of the contents of the string based on the innerHTML. It's easy to get rid of the previous contents/events in the container.
let str = ` `;
for (let i = 0; i < 10; i++) {
  str += `<span>${i}</span>`;
}
document.body.innerHTML = str; 
Copy the code
// Batch DOM setup based on document fragments: document fragments are temporary containers for DOM nodes
let frag = document.createDocumentFragment();
for (let i = 0; i < 10; i++) {
  let span = document.createElement("span");
  span.innerHTML = i;
  frag.appendChild(span);
}
document.body.appendChild(frag); 
Copy the code

‘Xiaohui is not easy, with praise oh 😝