Browser Render Frames

The mainstream PC screen refresh rate (FPS) is mostly at 60Hz, which means that the screen is refreshed 60 times per second, and the average refresh time is about 16.6ms.

  • If the refresh rate is higher than 60 frames /s, some useless refreshes will be done, wasting CPU resources.
  • When the refresh rate is lower than 60 frames /s (that is, when the user updates the page, the page content is not modified in time), frames will be lost, resulting in page lag and poor user experience.

So what do you need to do during a browser screen refresh? We illustrate this with the help of a browser rendering frame flow chart

  1. When a new frame starts, the user input event is first processed and the callback of related events (including but not limited to: Touch Event, Input Event, wheel Event and Click Event) is triggered.
  2. Search the Timer task list. If the time of the scheduled task expires, the scheduled task is executed.
  3. Execute the requestAnimationFrame callback registered in the last render frame (the requestAnimationFrame callback registered in this render frame will not be executed until the next render frame)
  4. Parse HTML. If there is a DOM change, there is the process of parsing the DOM
  5. Recalc Styles, this step recalculates the Styles of the specified element and its children if you modify the style or change the DOM during JS execution
  6. Layout. If there is a DOM change or style change involving the location of elements, the browser recalculates the location and size of all elements. Simply changing color, background, and so on does not trigger a rearrangement
  7. Update layer tree to Update the hierarchical sorting relationship of the Render layer
  8. Paint, calculates the Paint instructions for updating layers
  9. Composite, passes the draw instruction to the Composite thread
  10. If the Main Thread has time before the next frame arrives, the requestIdleCallback callback is executed
  11. The composition thread schedules rasterization and tells the GPU process to refresh the frame

Thus, an automatic screen refresh process is similar to page rendering

requestAnimationFrame

Previously we mentioned requestAnimationFrame, an API that registers callback functions with the browser and executes the callback before each rearrangement and redraw, generally used to optimize page performance

const element = document.getElementById('some-element-you-want-to-animate'); let start; function step(timestamp) { if (start === undefined) start = timestamp; const elapsed = timestamp - start; // Use 'math.min ()' here to make sure the element stops at exactly 200px. Element.style. transform = 'translateX(' + Elapsed, 200) + 'px '; If (elapsed < 2000) {/ / stop in two seconds animation window. RequestAnimationFrame (step); } } window.requestAnimationFrame(step);Copy the code

Note: if you want to in the browser to update until the next redraw the next frame animation, then the callback function itself must once again call window. RequestAnimationFrame ()

requestIdleCallback

As we can see from the frame execution cycle above, the lower priority code registered with requestIdleCallback will be executed after the browser completes the page rendering operation within one render frame (refresh cycle) and has time left. Such as:

const sleep = (delay) => { const start = Date.now() while (Date.now() - start < delay) {} } const tasks = [ () => { Log (' first task starts ') sleep(15) console.log(' first task ends ')}, () => {console.log(' second task starts ') sleep(5) console.log(' second task ends ')}, () => {console.log(' third task starts ') sleep(20) console.log(' third task ends ')}, () => {console.log(' fourth task starts ') sleep(10) console.log(' fourth task ends ')}, ] const start = Date.now() const worker = (deadline) => { while ( (deadline.timeRemaining() > 0 || deadline.didTimeout) && tasks.length > 0 ) { tasks.shift()() console.log(Date.now() - start) if (deadline.timeRemaining()) { Console. log(' continue ')} else {console.log(' Time is out, The next execution ')}} if (tasks) length) {window. RequestIdleCallback (worker, {timeout: 1000 }) } } window.requestIdleCallback(worker, { timeout: 1000 })Copy the code
  • Sleep is a simple sleep function used to simulate a timeout task
  • Tasks is a list of four tasks that we need to perform;
  • Worker is the low-priority code we need to execute;

Finally we call requestIdleCallback to register the low-priority code and execute the code block when the main thread is idle within the render frame (16.6ms). RequestIdleCallback receives two arguments:

  • Callback: a registered low-priority callback that takes in a Deadline object and contains a timeRemaining function to determine if there is any free time in the current rendering frame; DidTimeout Determines whether the timer time is up
  • Options: Usually we need to specify a timer for low priority code, indicating that if the timer expires, regardless of whether the main thread is idle, it should be enforced, such as {timeout: 1000}

Enter the above code in sequence:

conclusion

  • RequestAnimationFrame and requestIdleCallback are executed after the page is rearranged and redrawn, respectively;
  • RequestAnimationFrame is always executed before each redraw, requestIdleCallback is not always executed