Look at the browser rendering process and performance optimization from 7 interview questions

Preface

In the era of mobile Internet, users have higher and higher requirements for the opening speed of web pages. Baidu User Experience Department research shows that the relationship between page abandonment rate and page opening time is shown in the figure below.

Insert picture description here

According to the research results of Baidu User Experience Department, the page loading time that ordinary users expect and can accept is within 3 seconds. If the page loading time is too slow, users will lose patience and choose to leave.

As the first screen facing the user, the importance of the first screen is self-evident. Optimizing user experience is one of the things we need to focus on in front-end development.

In this article, we will talk about the browser rendering process and performance optimization through 8 interview questions.

Let's first take these 8 questions to understand the browser rendering process, and we will give solutions later~

  • Why is Javascript single-threaded?
    Bold style

  • Why does JS block page loading?

  • Will css loading cause blocking?

  • The difference between DOMContentLoaded and load?

  • What is CRP, namely Critical Rendering Path? How to optimize?

  • What is the difference between defer and async?

  • Talk about browser reflow and redraw?

Process and thread

Process and thread are the basic concepts of operating system.

进程是 CPU 资源分配的最小单位(是能拥有资源和独立运行的最小单位)。

线程是 CPU 调度的最小单位(是建立在进程基础上的一次程序运行单位)。

Modern operating systems can run multiple tasks at the same time, for example, you can listen to music while surfing the Internet with a browser.

对于操作系统来说,一个任务就是一个进程,For example, opening a browser starts a browser process, and opening a Word starts a Word process.

Some processes do more than one thing at the same time, such as Word, which can perform typing, spell checking, printing and other things at the same time.在一个进程内部,要同时做多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程。

Since each process has to do at least one thing, a process has at least one thread. The system allocates independent memory to each process, so the process has its own independent resources. Each thread in the same process shares the memory space of the process (including code segments, data sets, heaps, etc.).

To borrow a vivid metaphor, a process is like a production factory with a boundary, and a thread is like an employee in the factory, who can do their own things or cooperate with each other to do the same thing.

When we start an application, the computer will create a process, the operating system will allocate a part of the memory for the process, all the state of the application will be stored in this memory.

The application may also create multiple threads to assist the work, these threads can share the data in this part of the memory. If the application is closed, the process will be terminated and the operating system will release related memory.

Insert picture description here

Browser's multi-process architecture

A good program is often divided into several modules that are independent and cooperating with each other, and so are browsers.

Take Chrome as an example. It consists of multiple processes, each of which has its own core responsibilities. They cooperate with each other to complete the overall function of the browser.

Each process contains multiple threads, and multiple threads in a process will also work together to complete the responsibilities of the process.

Chrome adopts a multi-process architecture, and there is a Browser process on the top layer to coordinate other processes of the browser.Insert picture description here

advantage

Since a new tab page is opened by default and a new process is created, a single tab page crash will not affect the entire browser.

Similarly, the crash of third-party plug-ins will not affect the entire browser.

Multi-process can make full use of the advantages of modern CPU multi-core.

It is convenient to use the sandbox model to isolate processes such as plug-ins and improve the stability of the browser.

Disadvantage

The system allocates memory, CPU and other resources for the newly opened process of the browser, so the resource consumption of memory and CPU will be greater.

However, Chrome has done a good job in memory release. Basic memory can be released quickly for other programs to run.

The main processes and responsibilities of the browser

Insert picture description here

主进程Browser Process

Responsible for the display and interaction of the browser interface. Management of each page, creation and destruction of other processes. Network resource management, downloading, etc.

第三方插件进程 Plugin Process

Each type of plug-in corresponds to a process and is created only when the plug-in is used.

GPU 进程 GPU Process

There is only one at most, used for 3D drawing, etc.

渲染进程 Renderer Process

It is called the browser rendering process or browser kernel, which is multi-threaded internally. Mainly responsible for page rendering, script execution, event handling, etc. (This article focuses on analysis)

渲染进程 Renderer Process

The browser's rendering process is multi-threaded, let's see which main threads it has:

Insert picture description here

1 GUI rendering thread

  • Responsible for rendering the browser interface, parsing HTML, CSS, building DOM tree and RenderObject tree, layout and drawing, etc.

  • When the interface needs to be repainted or reflowed due to some operation, the thread will execute.

  • Note that the GUI rendering thread and the JS engine thread are mutually exclusive. When the JS engine is executed, the GUI thread will be suspended (equivalent to being frozen), and the GUI update will be saved in a queue until the JS engine is idle. .

2 JS engine thread

  • The Javascript engine, also known as the JS kernel, is responsible for processing Javascript script programs. (E.g. V8 engine)
  • The JS engine thread is responsible for parsing Javascript scripts and running codes.
  • The JS engine has been waiting for the arrival of tasks in the task queue, and then processing them. There is only one JS thread running the JS program in a Tab page (renderer process) at any time.
  • Note that the GUI rendering thread and the JS engine thread are mutually exclusive, so if the JS execution time is too long, this will cause the rendering of the page to be inconsistent and cause the page rendering to be blocked.

3 Event trigger thread

  • Belongs to the browser instead of the JS engine, used to control the event loop (understandably, the JS engine itself is too busy and requires the browser to open a thread to assist)
  • When the JS engine executes code blocks such as setTimeOut (also from other threads of the browser kernel, such as mouse clicks, AJAX asynchronous requests, etc.), the corresponding task will be added to the event thread
  • When the corresponding event meets the trigger condition and is triggered, the thread will add the event to the end of the queue to be processed and wait for the JS engine to process
  • Note that due to the single-threaded relationship of JS, the events in these pending queues have to be queued for processing by the JS engine (executed only when the JS engine is idle)

4. Timing trigger thread

  • The thread where the legendary setInterval and setTimeout are located
  • The browser timer counter is not counted by the JavaScript engine, (because the JavaScript engine is single-threaded, if it is in a blocked thread state, it will affect the accuracy of the timing)
  • Therefore, a separate thread is used to time and trigger the timing (after the timing is completed, it is added to the event queue and executed after the JS engine is idle)
  • Note that W3C stipulates in the HTML standard that a time interval lower than 4ms in setTimeout is counted as 4ms.

5 Asynchronous http request thread

  • After XMLHttpRequest is connected, a new thread request is opened through the browser.
  • When a state change is detected, if a callback function is set, the asynchronous thread will generate a state change event and put this callback into the event queue. Then executed by the JavaScript engine.

6 Supplement: web worker

Web workers are a way that javascript allows multithreading. It is another computing thread. See Ruan Dashen's log for details ;

Summary: The js we usually use is just a thread in the browser process. Many asynchronous operations, event callback management, etc. need to be processed by additional threads, and then the javascript thread is notified in the form of events.

Browser rendering process

If you want to talk about what happens from the input of the url to the page loading, it is endless...Here we only talk about the browser rendering process.
Insert picture description here

  • Parse HTML files, build DOM tree, and the main browser process is responsible for downloading CSS files

  • The CSS file is downloaded, the CSS file is parsed into a tree-shaped data structure, and then combined with the DOM tree to form a RenderObject tree

  • Layout the RenderObject tree (Layout/reflow), responsible for the calculation of the size and position of the elements in the RenderObject tree

  • Draw the RenderObject tree (paint), draw the pixel information of the page

  • The main browser process passes the default layers and composite layers to the GPU process, and the GPU process composites each layer (composite), and finally displays the page

answer

1.为什么 Javascript 要是单线程的 ?

This is due to the mission of the scripting language Javascript! JavaScript handles user interaction in the page, and manipulates the DOM tree and CSS style tree to present users with a dynamic and rich interactive experience and interactive processing of server logic.

If JavaScript is a multi-threaded way to manipulate these UI DOMs, there may be conflicts in UI operations.

If Javascript is multi-threaded, under multi-threaded interaction, the DOM node in the UI may become a critical resource.

Assuming that there are two threads operating a DOM at the same time, one is responsible for modifying and the other is responsible for deleting, then the browser is required to decide how to take effect which thread's execution result is.

Of course, we can solve the above problems by locking. But in order to avoid the greater complexity caused by the introduction of locks, Javascript chose single-threaded execution at the beginning.

2. 为什么 JS 阻塞页面加载 ?

Since JavaScript can manipulate the DOM, if you modify these element attributes while rendering the interface (that is, the JavaScript thread and the UI thread run at the same time), then the element data obtained before and after the rendering thread may be inconsistent.

Therefore, in order to prevent unpredictable results from rendering, browser settingsGUI 渲染线程与 JavaScript 引擎为互斥的关系。

当 JavaScript 引擎执行时 GUI 线程会被挂起,GUI 更新会被保存在一个队列中等到引擎线程空闲时立即被执行。

From the above we can infer that due to the mutually exclusive relationship between the GUI rendering thread and the JavaScript execution thread,

When the browser is executing the JavaScript program, the GUI rendering thread will be stored in a queue and will not continue until the JS program is executed.

Therefore, if the JS execution time is too long, it will cause the rendering of the page to be inconsistent, leading to the feeling of blocking the page rendering and loading.

3. css 加载会造成阻塞吗 ?

From the above browser rendering process, we can see:

DOM parsing and CSS parsing are two parallel processes, so CSS 加载不会阻塞 DOM 的解析.

However, since Render Tree is dependent on DOM Tree and CSSOM Tree,

So he must wait until the CSSOM Tree is built, that is, the CSS resource is loaded (or the CSS resource fails to load) before rendering.

therefore,CSS 加载会阻塞 Dom 的渲染。

Since JavaScript can manipulate the DOM and CSS styles, if you modify these element attributes while rendering the interface (that is, the JavaScript thread and the UI thread run at the same time), then the element data obtained before and after the rendering thread may be inconsistent.

Therefore, in order to prevent unpredictable results from rendering, browser settings GUI 渲染线程与 JavaScript 引擎为互斥的关系。

Therefore, the style sheet will be loaded and executed before the subsequent js is executed, socss 会阻塞后面 js 的执行。

4 DOMContentLoaded 与 load 的区别 ?

  • When the DOMContentLoaded event is triggered, only after the DOM parsing is completed, style sheets and pictures are not included. We mentioned earlier that CSS loading will block the rendering of Dom and the execution of js later, and js will block Dom parsing, so we can conclude that
    when there is no script in the document, the browser can trigger the DOMContentLoaded event after parsing the document. If the document contains a script, the script will block the parsing of the document, and the script needs to be executed after the CSSOM is built. In any case, the triggering of DOMContentLoaded does not need to wait for pictures and other resources to be loaded.

  • When the onload event is triggered, all DOM, style sheets, scripts, pictures and other resources on the page have been loaded.

  • DOMContentLoaded -> load。

5. 什么是 CRP,即关键渲染路径(Critical Rendering Path)? 如何优化 ?

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

In order to complete the first rendering as quickly as possible, we need to minimize the following three variables:

  • Number of critical resources: Resources that may prevent the first rendering of the web page.

  • Critical path length: The number of round trips or total time required to obtain all critical resources.

  • Keyword section: The total number of bytes required to achieve the first rendering of a web page is equivalent to the sum of the file sizes of all key resources.

1. Optimize the DOM

  • Delete unnecessary code and comments including spaces, and try to minimize files.
  • You can use GZIP to compress files.
  • Combined with HTTP cache files.

2. Optimize CSSOM

Reducing, compressing, and caching are equally important. For CSSOM, we mentioned earlier that it will prevent page rendering, so we can consider optimization from this aspect.

  • Reduce the number of key CSS elements
  • When we declare style sheets, please pay close attention to the types of media queries, they greatly affect the performance of CRP.

3. Optimize JavaScript

When the browser encounters the script tag, it will prevent the parser from continuing to operate. Until the CSSOM is built, JavaScript will run and continue to complete the DOM construction process.

  • async: After we add the async attribute to the script tag, the browser will continue to parse the DOM when encountering this script tag, and the script will not be blocked by CSSOM, that is, it will not block CRP.

  • Defer: The difference with async is that the script needs to be executed after the document is parsed (before the DOMContentLoaded event), while async allows the script to run in the background during document parsing (the download process of the two will not block the DOM, but the execution will).

  • When our script does not modify the DOM or CSSOM, it is recommended to use async.

  • Preload-preload & prefetch.

  • DNS pre-resolution-dns-prefetch.

6. defer 和 async 的区别 ?

When the browser encounters the script script:

  • <script src="script.js">
    Without defer or async, the browser will load and execute the specified script immediately. "Immediately" refers to the document element under the script tag before rendering, that is to say, it does not wait for the subsequent loaded document element, and loads it when it is read. And execute.

  • <script async src="script.js">

With async, the process of loading and rendering subsequent document elements will be parallel to the loading and execution of script.js (asynchronous).

  • <script defer src="myscript.js">
    With defer, the process of loading subsequent document elements will be performed in parallel with the loading of script.js (asynchronous), but the execution of script.js must be completed after all elements are parsed and before the DOMContentLoaded event is triggered.

From a practical point of view, it is best practice to throw all the scripts before, because this is the only optimization choice for old browsers. This method can ensure that all other elements that are not scripts can be obtained at the fastest speed. Loading and parsing.

Next, let's look at a picture:Insert picture description here

The blue line represents network reading, and the red line represents execution time, both of which are for scripts. The green line represents HTML parsing.

Therefore, we can conclude:

  • Defer and async are the same in network reading (downloading), both are asynchronous (compared to HTML parsing)

  • The difference between the two is when the script is executed after the script is downloaded. Obviously defer is the closest to our requirements for application script loading and execution.

  • Regarding defer, the unfinished part of this picture is that it executes scripts in the order of loading, which should be used wisely

  • async is a master of out-of-order execution. Anyway, for it, the loading and execution of scripts are next to each other, so no matter what order you declare, it will be executed immediately as long as it is loaded.

  • Think about it carefully, async is not very useful for application scripts, because it does not consider dependencies at all (even the lowest order execution), but it is not dependent on any script or scripts that are not dependent on any script. Very suitable

7.谈谈浏览器的回流与重绘

回流必将引起重绘,重绘不一定会引起回流。

Reflow

When the size, structure, or some properties of some or all elements in the Render Tree change, the process of the browser re-rendering part or all of the document is called reflow.

Operations that will cause backflow:

First rendering of the page

The browser window size has changed

The size or position of the element changes. The content of the element changes (number of text or image size, etc.)

Element font size changes

Add or remove visible DOM elements

Activate CSS pseudo-classes (for example: :hover)

Query certain properties or call certain methods

Some commonly used properties and methods that will cause reflow:

clientWidth、clientHeight、clientTop、clientLeft

offsetWidth、offsetHeight、offsetTop、offsetLeft

scrollWidth、scrollHeight、scrollTop、scrollLeft

scrollIntoView()、scrollIntoViewIfNeeded()

getComputedStyle()

getBoundingClientRect()

scrollTo()

Repaint

When the change of the element style on the page does not affect its position in the document flow (for example: color, background-color, visibility, etc.), the browser will assign the new style to the element and redraw it. This process is called re-drawing. painted.

Performance impact

回流比重绘的代价要更高。

Sometimes even if only a single element is reflowed, its parent element and any elements that follow it will reflow. Modern browsers will optimize frequent reflow or redraw operations: the browser will maintain a queue and put all operations that cause reflow and redraw in the queue. If the number of tasks in the queue or the time interval reaches a threshold, The browser will empty the queue and perform a batch process, which can turn multiple reflows and redraws into one.

When you access the following properties or methods, the browser will immediately clear the queue:

clientWidth、clientHeight、clientTop、clientLeft


offsetWidth、offsetHeight、offsetTop、offsetLeft


scrollWidth、scrollHeight、scrollTop、scrollLeft


width、height


getComputedStyle()


getBoundingClientRect()

Because there may be operations in the queue that affect the return values ​​of these properties or methods, even if the information you want to get is not related to the changes caused by the operations in the queue, the browser will forcibly empty the queue to ensure that the value you get is the most accurate .

How to avoid

CSS

  • Avoid using table layout.

  • Change the class at the very end of the DOM tree as much as possible.

  • Avoid setting multiple inline styles.

  • Apply animation effects to elements whose position attribute is absolute or fixed.

  • Avoid using CSS expressions (for example: calc()).

Javascript

  • To avoid frequent manipulation of styles, it is best to rewrite the style attribute once, or define the style list as class and change the class attribute once.

  • Avoid frequently operating the DOM, create a documentFragment, apply all DOM operations on it, and finally add it to the document.

  • You can also set display: none for the element first, and then display it after the operation is over. Because DOM operations performed on elements whose display attribute is none will not cause reflow and redraw.

  • Avoid frequently reading attributes that will cause reflow/redraw. If you really need to use them multiple times, use a variable to cache them.

  • Use absolute positioning for the element with complex animation to make it out of the document flow, otherwise it will cause frequent reflow of the parent element and subsequent elements.

Guess you like

Origin blog.csdn.net/qq_29722281/article/details/105710839