At first I just wanted to understand how JS works in the browser. I found that I needed to fix the basics, so I decided to summarize an article to fix the basics and ask for correction if there was anything wrong.

This article is divided into several chapters to summarize the knowledge points I have learned, and review some basic computer knowledge, to understand how JS code is executed in the browser, how to render the page.

Processes and threads

– A process is a factory that has its own independent resources and is independent of each other;

– Threads are workers in a factory. Multiple workers collaborate to complete tasks in the factory.

– There may be one or more workers in the factory;

– Shared space between workers;

Then let’s look at the picture below and explain it a little bit more.



First of all, a computer can have many applications, and a browser is one of them. Browsers can have many modules (processes), each of which is independently assigned its own resources (threads).

1. An application is composed of one or more modules. For example, Google Chrome now has a main browser process, a GPU process, a network process, multiple rendering processes and multiple plug-in processes.

2. A process is composed of one or more threads. Threads are the basic unit of a process.

3. Processes are independent of each other and have their own resources, such as CPU time slices and memory.

4. Threads (workers) in a process share the resources of the process (factory), including code segments, data segments, memory, and so on.

5. Threads collaborate to complete tasks in the process.

6. A process is the smallest unit of CPU resource allocation, the smallest unit that can own resources and run independently.

7. Threads are the smallest unit of CPU scheduling because processes can have one or more threads.

Browsers are multi-process

Browsers are multi-process, with a master process and a new process for each TAB page (in some cases, multiple tabs merge processes, such as multiple blank pages). Take the current mainstream Google Browser for example, it mainly includes the following processes

1. Browser main process: there is only one browser main process, which is responsible for coordinating and controlling the browser

  • Responsible for browser interface display, user exchange, forward and backward, etc
  • Responsible for interface management, create/destroy other processes
  • Draw an in-memory Bitmap from the Renderer process onto the user interface
  • Network resource management, download, etc

2.GPU process: a maximum of one GPU process is used for 3D drawing

3. Plug-in processes: A process is created for each type of plug-in used

4. Browser rendering process (kernel) : by default, a new TAB is created every time a TAB is opened. Non-interference, control page rendering, script execution, event handling, etc. (Sometimes optimized, such as multiple blank TAB pages combined into one)



As shown here, open task Manager and open three tabs to create three processes. Responsible for controlling the rendering of your own page content. So why are browsers multi-process? If you are in a single process and one TAB freezes or crashes, it will affect other tabs

Browser renderer (kernel)

For these processes in browser applications, we only need to know that there is only one main browser process and multiple collaborative processes (Gpus, renderers, web processes, plug-in processes, and so on). The front end just needs to focus on the rendering process. Because the rendering process renders the page. And then this rendering process, it’s multithreaded, and if you don’t understand the relationship between processes and threads, think of the relationship between factories and factories. Let’s go back to the diagram and understand the relationship between processes and threads.



GUI rendering thread

GUI rendering thread is mainly responsible for rendering the page, parsing HTML, CSS, to build a DOM tree and render tree; This thread executes when the interface needs to be redrawn or rearranged to cause backflow. Note that the GUI rendering thread and JS engine execution are mutually exclusive. When the JS engine is executing, the GUI thread is suspended and stored in a task queue until the JS engine thread is idle and immediately executed. If it is not mutually exclusive, you will render the interface inaccurately while the user runs it, which determines that JS is single threaded. It can be summarized as follows:

  • Rendering interfaces, parsing HTML, CSS, building DOM trees and renderObject trees, layout and drawing, etc.
  • This thread is executed whenever an interface needs to be redrawn or an operation needs to be redrawn
  • GUI threads and JS engine threads are mutually exclusive

JS engine thread

Responsible for processing JS scripts, parsing scripts to run code. But the JS engine waits for the queue to arrive and then processes it. Also, the GUI rendering thread and JS engine execution are mutually exclusive, and if the JS execution is too long, the page rendering will be incoherent, i.e. blocking the page, and the page rendering load will be blocked, which is why script tags are often not placed in the header but under the bottom of the body. It can be summarized as follows:

  • Also known as the JS kernel, it handles Javascript scripts. (For example V8 engine)
  • The JS engine thread is responsible for parsing and running Javascript script code.
  • Will the JS engine wait for tasks to arrive in the task queue and then process them, and at any given time only one JS thread is running in a Tab page

  • Similarly, GUI threads and JS engines are mutually exclusive at execution time

Event lop

This event-triggering thread belongs to the browser, not the JS engine, so it can be understood that because the JS engine is single-threaded, it is busy, and it has to be assisted by the helper thread to complete some events, and these things are called event loops.

When the JS engine executes some asynchronous code blocks such as network requests and setTimeOut, it will add these asynchronous tasks to the event thread. When the task is eligible for processing, the thread adds the task to the end of the queue. Wait for the JS engine to execute. When the JS engine is empty, the queue will execute the task.

  • This thread belongs to the browser, not the JS engine, and is used to control the event loop mechanism
  • When the JS engine executes a code block such as setTimeOut (or other threads from the browser kernel, such as mouse clicks, AJAX asynchronous requests, etc.), it adds the corresponding task to the event thread
  • When the corresponding event meets the trigger condition is triggered, the thread will add the event to the end of the queue to be processed, waiting for the JS engine to process
  • Since JS is single threaded, all of these events have to queue up for the JS engine to execute. (Out of the queue when the engine is idle)

Timing trigger thread

The browser timer is not timed by the JS engine, because the JS engine is single-threaded. If you execute these calculators, the blocking page stops completely, and the user doesn’t need to click on the web page. Therefore, a separate thread is used to time and trigger the timing. When the timing is finished, it is added to the event queue and wait for the JS engine to be idle. It can be summarized as follows:

  • SetInterval and setTimeout Specifies the thread to be timed
  • After the timing is complete, it is added to the event queue and waits for the JS engine to execute. (execute when the JS engine is idle)
  • W3C stipulated in the HTML standard that setTimeout interval less than 4ms should be counted as 4ms.

Asynchronous HTTP request threads

After the XMLHttpRequest connects, a new thread is requested through the browser. When a state change is detected, if a callback function is set, the asynchronous thread generates a state change event and places the callback into the event queue. It is then executed by the JS engine.

  • After the XMLHttpRequest connects, the browser opens a new thread request
  • When a state change is detected, if a callback function is set, the asynchronous thread generates a state change event and places the callback in the event queue. It’s executed by the JavaScript engine.

At this point, you should have an idea of what happens when your browser opens a page. If not, go back. There is always an event queue mentioned above, which thread is it based on? The answer is the event-triggering thread

Communication between the browser main process and other processes

The Browser main process is originally the main process of the browser, and is the main process that controls and coordinates other processes. When a Tab page is opened, a main thread is created. Coordinate with other threads to complete page rendering through the main thread. This is going to involve some parallel operating systems, so I won’t expand it, and I’ll just review the whole process.



  • When the Browser main process receives a user request, it first needs to fetch the page content (such as downloading a resource through a network process) and then passes this task to the resource Render process through the RendererHost interface
  • The Renderer interface of the Renderer process receives the message, briefly explains it, passes it to the Renderer thread, and begins rendering

    • The render thread receives the request, loads the web page, and renders the web page. This may require the Browser main process to obtain resources and the GPU process to help render, which is completed by the main process scheduling helper process.
    • Of course there could be JS threads manipulating the DOM (this could cause backflow/redraw)
    • Finally, the Render process passes the result to the Browser process
  • The Browser main process receives the results of each collaborative process and draws them

Tips: If you dig deep into this part of the process, you can write dozens of articles, and the front end can understand the collaboration of the whole process

Tease out relationships between browser rendering threads

The renderer process, the browser kernel, is where our front-end focus is, again. Then we have to know a few points.

  1. GUI threads and JS engine threads are mutually exclusive
  2. Because of point 1, if the JS engine takes a long time to execute, the page will block
  3. HTML5 supports Web workers to solve page blocking, but Web workers are JS engine sub-threads, controlled by the JS engine, JS single threads remain unchanged

Browser Rendering process

This process is also quite complicated, as you can refer to my previous computer networking (front-end version) problem, which is not described in too much detail here. This is just a brief description

1. The browser enters the URL. The main thread of the browser takes over. (Ignore DNS, etc.)

2. Take the response and pass it to the Renderer process through the RendererHost interface

3. The browser starts rendering (possibly coordinating with GPU threads)

Once the rendering process (kernel) gets the content, it starts rendering in the following steps:

1. Parse HTML to build a DOM tree

2. Parse CSS to build the render tree, in fact, is about CSS to parse into a tree data structure, and then combine dom tree to form the render tree.

3. Render tree (Layout/reflow), complex calculation of the size of the element, location and other information

4. Start rendering the Render tree, drawing the page pixel information

5. The browser will send the drawing information to the GPU, and the GPU will display the composite on the screen.

The steps are not detailed, just list a general, more detailed please refer to other rendering articles, here do not go into depth.

Tips: This is why page rendering triggers backflow at least once.

Here’s a diagram to tease out the steps above:



Attention to detail

  1. The DOMContentLoaded event is triggered only when the DOM is loaded, not including stylesheets, images. Scripts with async may not be complete.
  2. When the onLoad event is triggered, all the DOM, stylesheets, scripts, and images on the page have been loaded. The page is rendered.
  3. CSS loading does not block DOM tree parsing (the DOM is built as usual for asynchronous loading); But it blocks the render tree until the CSS is loaded because the render tree needs CSS information.
  4. The concept of composite is mentioned in the rendering step. It can be simply understood that browser rendering layers generally include two categories, namely ordinary layers and composite layers.
  5. The document can be used as a compound layer by default, and absolute, which is removed from the document flow, is still a compound layer. I’m not going to describe hardware acceleration here.

JS Event Loop

At this point, the page has finished its first rendering.

Event lop is actually the event trigger thread (the queue maintained by the thread) in the render process, if you don’t remember, scroll up to remember. It actually works with the JS engine thread to complete the task. (Some interface interchange)

To recap, the browser renderer has three threads:

  • JS engine thread
  • Event trigger thread

  • Timed trigger thread

The main execution stack of the JS engine is:

1.JS includes synchronous tasks and asynchronous tasks

2. All synchronization tasks are executed on the main thread, forming a main execution stack

3. In addition to the main thread, the event-triggering thread manages a task queue (the task queue mentioned above) and enlists an event in the task queue whenever the asynchronous task has a running result.

4. Once all synchronous tasks in the main execution stack are completed (at this time, the JS engine is idle), the system will read the task queue, add the asynchronous tasks that can be run to the executable stack, and start the execution cycle.



Sometimes events pushed by setTimeout do not execute on time. Because the main thread may not be idle and executing other code when it is pushed into the event list, there is an error.

conclusion

The browser principle is still very complex, understanding its rendering principle, can help us optimize performance. Specific details like Event lop, Event looping mechanisms, rendering principles, etc. You can refer to the big guy’s article, I only make a small extension here.

Reference article:

Yuchengkai. Cn/docs/fronte…

Sanyuan0704. Making. IO/frontend_da…