First of all, before we talk about backflow and redraw, we need to know, where are these two processes in the rendering of the page?

The key rendering steps of the browser are divided into the following steps

parsing

(1) Parsing HTML files to build a DOM tree

(2) Parsing CSS to build cssOM

(3) Combine DOM and cssOM into a rendering tree

draw

(1) Layout according to render tree (Backflow)

(2) Draw according to the layout (redraw)

Composite layer

Merge the redraw and reflow layers and display them on the screen

backflow

Backflow mainly refers to rendering where geometric properties need to be changed. The geometry of the render tree node changes, causing its position to change, resulting in recalculation to generate a new render tree. This is the main reason why backflow costs performance, because it recalculates the DOM generated.

redraw

Redraw refers to changes in appearance properties. It affects the appearance of nodes, but does not affect their geometry. But the change of geometry will definitely affect the change of appearance.

Performance optimization

  • Multiple reads or writes are placed together to reduce the number of reflows and redraws.
  • Don’t change styles multiple times, change classes instead
  • With the offline DOM, the node to be manipulated is placed in the DocumentFragment and then inserted into the corresponding node after the operation is complete, so that backflow and redraw only occur during insertion
  • You can set the DOM to display: None and then manipulate the DOM so that only two rerenders are performed.
  • Setting DOM to position: Absolute or fixd reduces the overhead of backflow.
  • Backflow and refactoring are related to event loops. The typical screen refresh rate is 60HZ, which is one render every 16.66 milliseconds, which means that each task needs to be completed in this time per JS thread. This requires requestAnimationFrame and requestIdleCallback optimizations.

window.requestAnimationFrame()

RequestAnimationFrame in MDN tells the browser that you want to execute an animation and asks the browser to call the specified callback to update the animation before the next redraw. This method takes as an argument a callback function that is executed before the browser’s next redraw

RequestAnimationFramez ensures that the animation is executed only once per render interval, depending on the screen refresh rate.

When using setInterval to process animation, the execution time of animation will not be the same as expected due to asynchronous reasons, and we need a fixed time to execute animation, too short time will cause frame loss and consume more performance, and too much time will cause frame loss and lag. RequestAnimationFrame advantages: (1) CPU saving: requestAnimationFrame stops execution when a page is hidden or minimized. However, timers are constantly executed, which is a waste of CPU. (2) requestAnimationFrame groups DOM operations on the same frame together, resulting in only one redraw and reflow.

window.requestIdleCallback()

MDN introduction: window. RequestIdleCallback () method will be called function in browser free time line. This enables developers to perform background and low-priority work on the main event loop without affecting the delay of critical events such as animations and input responses. Functions are typically executed in first-come-first-called order; however, if a callback function specifies a timeout, it is possible to scramble the order of execution in order to execute the function before it times out. The browser executes the requestIdleCallback method at the idle time of each frame, but its second argument sets the execution time. If the requestIdleCallback callback is not executed at each frame, the requestIdleCallback method is executed at that time. reference

requestIdleCallback(function someHeavyComputation(deadline) { while(deadline.timeRemaining() > 0) { doWorkIfNeeded(); } if(thereIsMoreWorkToDo) { requestIdleCallback(someHeavyComputation); }});Copy the code

The deadline argument to the callback function has two methods. The timeRemaining() method returns the remaining milliseconds of the current frame. This method can only be read, not written. The didTimeout attribute of the Deadline object returns a Boolean value indicating whether the specified time is expired.