preface

  • This article will take about 15 minutes \color{red}{15 minutes}
  • In this
    detailed \color{red}{red}
    A:

    1. Processes and threads
    2. Browser rendering mechanism detailed parsing process
    3. Summary of CRP key node optimization scheme
    4. Refluxing and repainting
    5. The render queue mechanism of modern browsers
  • If you have any questions, please leave a message to me. I will reply when I see it. If I can’t solve it, we can also discuss and learn together. If you think there is any mistake, please kindly comment and correct me. Thank you very much. I hope to learn and make progress together with you in the future.
  • The next article will be updated as soon as possible, and the already written article will be modified intermittently in the future as understanding deepens or illustrations are added.
  • If you find this article helpful, please give it a thumbs-up. Thank you!

Processes and threads:

  • Process:

    • A program, eg a process created when the browser creates a new page card
  • Thread:

    • A process may contain multiple threads, but each thread can do one thing at a time [worker]
    • To truly do more than one thing at a time, you have to rely on multithreading
    • Browsers are multithreaded [browser asynchro: you can do multiple things at once]
    • JS is single threaded.
  • Threads in the browser:

    • GUI rendering thread: Renders the page from top to bottom
    • JS engine threads: Render and execute JS code
    • Event-triggered thread: During event binding, there is a thread that listens for the event to be triggered. Once the event is triggered, this thread notifies 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 notify the corresponding method to execute when the time is up
    • Asynchronous HTTP request thread: allocate a thread to fetch content from the server [CSS /js/img/ data…]
    • webWorker
  • JS code execution [single thread] [is also with the browser multi-thread to achieve some asynchronous operation]

    • But JS itself is single-threaded (because the browser itself only allocates one thread to run the JS code)
    • In essence, JS cannot do more than one thing at a time.
    • JS single thread can also achieve asynchronous effect, is the use of browser multithreading to complete
      • [sync] : Move on to the next thing after the last thing is done
      • [asynchronous] : The last thing is not done (we do some processing (Take advantage of the browser’s multithreading(The next thing goes on
  • The process of the browser generating DOM tree, CSSOM tree… is itself a single thread. It is also with the multi-thread browser to achieve some asynchronous operation.

    • Browser generated DOM TREE, CSSOM-TREE… Is ‘GUI render thread ‘process by process, process is single thread
    • Resource requests, for example, are made using the browser’s HTTP thread (the network thread)

Browser rendering mechanism of the specific parsing process:

1. When the browser gets the HTML page from the server, it assigns a GUI rendering thread to render and parse the code from top to bottom

  1. If tags such as < Audio >

    are encountered, a new thread (HTTP request thread) is allocated to fetch the resource file, while the GUI continues rendering down (regardless of whether the resource comes back). “No blocking GUI rendering!!”
  2. If
  3. If you encounter@import "xxx.css"At this point, the GUI stops rendering and assigns a new HTTP thread to fetch the resource file. It must wait until the resource file returns before the GUI continues rendering and parses the obtained CSS code….“Will hinder GUI rendering !!!!”
    • [Corresponding optimization] Do not use it in the project as far as possible@importExclude import from less and sess, as the code is compiled@importNo 】
    • If the corresponding optimization 】 【 CSS code is less, can be used directly embedded, reduce the number of HTTP requests, make the code rendered more timely [page open speed is faster for the first time] if the code is more, or use outside the chain to separate into style, and it’s the main code and convenient maintenance, not request HTML page will be a long time

2. [Step 1] After completing all HTML tags/various nodes through top-down parsing, generateDOM TREE

  • Render and parse DOM structures and map out the relationships between nodes
  • After the DOM TREE is generated, an event, DOMContentLoaded, is triggered
  • [Optimization] Avoid nested DOM hierarchies too deep

3. [Step 2] Wait for all CSS resource requests to come back, according to the order of import, render CSS styles in turn, to ensure that CSS rendering order and priority, etc., generatedCSSOM TREE

  • 【 optimize 】 we put<link>In the HEAD tag, send the resource request before rendering the DOM, so that by the time the DOM TREE is generated, the CSS resource may have been requested back, and render directly…. (Doing things at the same time can speed up the first rendering of the page.)
    • Since the number of concurrent HTTP requests on a page is 5~7
    • Also, too many requests can clog network channels, and there are many other reasons why sending HTTP requests multiple times is not as fast as sending them once
    • So in the project, we need to merge all CSS resources into one file!! It also eliminates the need to worry about the loading and rendering order of multiple resource files.

4. [Step 3] Put the generatedDOM TREECSSOM TREEMerged withRENDER TREE【 Render tree 】

  • The render tree contains the style that each node should have when the browser renders it.

5. [Step 4] Follow the browser instructionsRENDER TREEBegin to render

  1. 【 layout 】: Based on currentviewportViewport size Calculates the position of each node in the viewport
  2. [Layering] : Build the document flow of each layer, and plan how each layer is drawn [the drawing steps are calculated]
  3. Painting: Start painting the page according to the analyzed rules and finally render the page we want in the browser viewport

6. [JAVASCRIPT] In the process of page rendering, encountered<script>The resource request

  • Encountered by default<script>Resource requests will block GUI rendering
    1. Send an HTTP request to get the resource file, blocking GUI rendering
    2. Once the resource is acquired, it is handed over to the JS engine thread to render and parse the JS
    3. JS parsing completes, GUI continues
  • But if you give<script>Setting defer or Async will not block GUI rendering
    1. <script>: Resource requests and JS execution both impede the GUI
    2. <script async>: The resource request does not block the GUI. When the resource request comes back, the GUI will immediately render and parse the JS. At this point, the GUI will stop rendering
    3. <script defer>: Resource requests do not block the GUI, no matter when the resource request comes back, it does not render the JS immediately after the resource request comes back, it waits until the GUI rendering is complete, and finally executes the JS in the order of import.
    4. The difference between async and defer is that async does not take into account the JS order relation. However, defer needs to wait until all the requested resources come back and the GUI rendering is complete before executing the JS in dependent order

Summary of optimization scheme:

  1. Avoid deep DOM hierarchy nesting ———> Speed up DOM TREE generation
  2. CSS selectors are rendered from right to left, so CSS selectors avoid long prefixes ——> speed up the generation of CSSOM TREE
  3. Preference for
  4. Use for too many styles, but combining all CSS resources into a SINGLE CSS style file (webpack can automatically pack) ———> reduces HTTP requests & links and does not hinder GUI rendering
  5. Put in the page header ————> While creating the DOM TREE, request the resource file
  6. Resolute don’t@import【 Exclude sess and less】
  7. Generally,
  8. The project also needs to combine all JS resources into a single JS file to reduce HTTP requests.
  • The goal of optimization is to make the page render faster and the white screen wait time shorter

  • Refluxing and repainting

  • Layout 【 return/rearrange 】

    • The first time a page loads, it must experience oneLayout 【 return/rearrange 】To calculate the position of each node in the viewport[First loading]
    • When an action occurs that causes a rearrangement, the browser needs to recalculate the position of each node in the viewport (or recalculate the layout information), i.elayoutOnce, such an operation is very costly to page rendering performance, this is called rearrangement or backflow.
    • Rearrangement inevitably leads to redrawing, redrawing does not lead to rearrangement
    • [Certain conditions that cause backflow]

      • DOM element additions, deletions and changesCauses DOM structure to change
      • The style of the DOM[DOM style changes]
      • Changes in content, resulting in size changes.
      • Backflow can also occur when the browser window size changes[View/viewport changes]
    • Ways to avoid DOM backflow

      1. [First of all: abandon the traditional DOM operation], use VUE, React and other frameworks, based on data driven, to achieve view rendering [Essence: the framework itself encapsulates DOM operation, and internally realizes DOM optimization]
      2. [Read-write separation operation][Render queue mechanism based on modern browsers]
        • For DOM element styles in a real project, we should ‘read/write’ : separate the set style and get style operations, and then get the style after the whole thing is set to reduce the number of backflow
      3. 【 Element batch modification 】Temporary Container Document Fragment [Concatenated String]
        • CreateDocumentFragment Creates a document fragment

          • Create a document fragment, which is equivalent to a temporary container. Dynamically created elements are first put into the temporary container, and are not put into the DOM structure of the page temporarily, so that the page will not cause backflow. When the final dynamic modification is finished, the unified addition will reduce backflow as much as possible
              // Create a document fragment, which is equivalent to a temporary container. Create five spans and put them into the temporary container
              // Only one backflow will result
              let frag = document.createDocumentFragment();// Create a document fragment
              for(let i=1; i<=5; i++){
                      let span = document.createElement('span');
                      span.innerHTML = i;
                      farg.appendChild(span);// Create five spans and put them in temporary containers, not in the page DOM structure
                  }
                  box.appendChild(frag);// Add it once to box
                  frag = null;// Clear document fragments
          Copy the code

        • String concatenation [involves low-level browser parsing, so its performance is worse than document fragmentation]

              for(let i=1; i<=5; i++){
                  str+=`<span>${i}</span>`;// Concatenate the span added to the loop into a string
                  }
                  box.innerHTML = str;// Add it once to box
                  // Only one backflow will result
          Copy the code

      4. Cache layout information based on read/write separation
      5. Div. Style. cssText = ‘width:10px;height:10px;…’ div. ClassName = ‘box’;
      6. Layering to speed up reflux [Unchanged layering does not backflow]
      7. Hardware acceleration with CSS3 (GPU acceleration)
        • Modify the transform, opacity… Styles do not cause DOM rearrangements in the original document flow.
        • Changing the element’s transform removes the element from a single document stream, and the browser recalculates the position and layout of the document stream without affecting the original document stream…
        • Opacity is no longer visible, but still exists in the structure, so it does not cause backflow
        • transform 【 Skip render-tree and layout】Telling the composition thread to render directly will only cause a redraw
        • Similarly, we modify the style of elements later, as much as possible, to change the style of those elements that are out of the document flow, so that when we recalculate the layout information later, it is better to recalculate only the document flow, rather than the whole recalculation.
  • Redraw [inevitable]

    • The first time a page is rendered it must experience onepaintingDraw to draw the page
    • The style of the element changes (but the geometry and structure information remains the same in width, height, size, position, etc.)There’s no need for backflow,All you need is for the browser to rerender the changed elements.
    • [Trigger redraw situation]
      • color
      • background-color
      • Background-image 【 mainly check whether the geometry information of the current container/box is changed after the background image is changed. If it is changed, the background-image is redrawn. 】
      • Animation transform
      • .
  • When we say ‘manipulating the DOM costs performance’, we mostly mean DOM rearrangement!! So reducing DOM rearrangement is an important indicator of front-end performance optimization

  • In modern browsers:

    1. The last line of code changed the element style, and instead of telling the browser to render it, it placed it in the browser’s render queue and continued
    2. Whenever a style change is encountered, it is placed in the browser’s render queue
    3. When there is no more operation to modify the style, or when there is an operation to get the style (box model or get the style), it interrupts the operation to the queue and renders the operation to the style in the existing queue first (causes a backflow).
    4. Continue to execute the code, and if you encounter a style change again, do so again…