preface

Recently the company is relatively busy, coupled with the heavy good drama hidden corner attack, heavy learning front department fell behind, recently idle, continue! As a front-end engineer, aside from the editor, the browser is of course the most important thing we deal with, and we use it every day, but we don’t know about it. Here’s some soul searching for you!

  • 1. Why do you put CSS first and JS last when writing code
  • 2. Is the browser single-threaded or multi-threaded
  • 3. Why bubble and capture
  • 4. How do browsers implement asynchrony
  • 5. Why microtasks and macro tasks
  • 6. Why is caching the most important performance optimization tool
  • 7, why do closures cause memory leaks, browser JS engine garbage collection mechanism, why not reclaim it
  • 8. How do browsers work

Put these questions first for the time being, do not know whether you can catch it? In fact, I also a lot of clouds in the fog, next we slowly analyze, study together, step by step analysis

How does a browser work

To solve these problems, the first thing we need to know is how does the browser work?

To see the page, can not do without the network, after the network, of course, have to set a protocol, that is the famous HTTP, or HTTPS protocol, then he is how to deal with it,

First, when the network is open, enter a web address, and the browser will resolve the current domain name, and then pass the abnormal part of the domain name to the DNS client, and the client will send a query message to the DNS server to obtain the server IP address corresponding to the domain name. Then, The browser will initiate the HTTP request (NDS resolution process is not described here, if you are interested in the DNS resolution process). The specific HTTP protocol is not described here, please go to (HTTP soul question, strengthen your HTTP knowledge).

Now, let’s talk about how our browsers work and let’s get a few terms straight

Threads and processes

What is a process and a thread, in fact, in the words of the boss is summed up: a process and a thread are a description of a time, is the DESCRIPTION of the CPU work time.

On our Browser I understand is, first of all browsers have a Browser process, main process, responsible for the coordination and control, there was only one of the following, GPU, and some plug-in process, etc., we open a TAB to open the web page, it will open a Browser rendering process, and a number of different modules to deal with the web page, For example, js parsing module, HTTP request module, so that’s multiple threads, and the multiple threads can work together, and you can see that because I have multiple tabs open there are multiple processes, and there’s a main process for Google Chrome

So what are the important threads in the browser?In this case, the JS engine thread and the render thread are mutually exclusive, not because browsers can’t do multi-threaded concurrent execution, but because if you use JS to manipulate the DOM while rendering the DOM, who should you listen to? Because of the mutual exclusion, if our JS execution time is too long, the browser will always be unable to render, which causes the lag. These problems are the operating mechanism of the browser, and hence the clever surrender mechanism like React Fiber was created to solve the lag problem.

Does this give you a deeper understanding of how these frameworks work?

Does that explain the first question

The reason we put CSS in front is because the browser kernel (rendering process) allows multiple threads to work at the same time, so if we put CSS in front, we can parse the page and request CSS to parse the CSS at the same time. The reason we put JS in front, as we said, is that JS is a single thread, so if we put it in front, Then the parsing of JS will interfere with the rendering of the page, making the page unable to normally reach the conditions of the first rendering, affecting the user experience. In addition, because JS can operate dom but dom has not been rendered at this time, it is likely to appear weird bugs

What is a state machine

Now that we understand processes and threads, it’s time to start looking at the browser’s rendering process. How do browsers parse HTML code and build the DOM? Let’s start with a picture

HTML is essentially a character stream containing the tag, then the browser based on his code format to compile into the corresponding string, such as using utf-8 next, state machine, is our leading role in the browser rendering engine, it is through the state machine will parse a string into the corresponding word token (token refers to the compiling principle of contents, Each part of the tag is a token, such as a piece of HTML

<div class="aa"> </div> // it will be split into <div // tag start class="aa"// attribute >// start tag endCopy the code

And our analysis will need to use the state machine to implement, in fact, each of us read one character at a time, the browser will need to make a decision, quick to judge, it belongs to that kind of token, thus the token character split into independent state, and then in the token together, forming a connection diagram (only I understand, wrong place, After we split the dom tree into tokens, we can build a DOM tree, but first we need to understand a noun — stack

The stack

Stack: A data structure in which advanced data is at the bottom and last to be retrieved, and backward data is at the top and first to be retrieved.Copy the code

Almost all languages have a stack, which is an essential part of the data structure. Our HTML lexical analyzer uses a stack, so how does it parse? As it involves the knowledge of compilation principle, I am not very familiar with it, so here roughly say what I understand wrong place please big guy correct, follow the principle of advanced after out, such as parsing the following code

< p > < span > to learn < / span > < / p > < p / / / / < first into the stack span / / into the stack, determine the father-son relationship Study well < / span > / / / / into the stack into the dom structure of stack < / p > / / parent-child relationships have been identified, the stackCopy the code

At this point, the DOM tree is formed through the stack structure

So far the browser rendering process is clearly visible, and here is a summary

  • 1, enter the url, initiate HTTP request page character stream
  • 2. Parse HTML to form a DOM tree
  • 3. Parse CSS to CSSOM (note that parsing does not affect each other, but rendering does)
  • 4. Stop rendering when js is encountered
  • 5. Render one by one according to CSS properties to get the bitmap in memory
  • 6, start synthesis, call GUI thread drawing to interface (it is worth noting that the browser is not necessarily all the dom parsing the page, such as to render, but, to apply colours to a drawing conditions, can be rendered for the first time, but searching books there is no detailed official information, if you are interested please look at the practice of a heavyweight for browser rendering time point of exploration for the first time)

How exactly is the browser EventLoop asynchronous

Why do browsers need to implement asynchrony

The reason why browsers need to implement asynchronous, is because JS is a single-threaded language, and there is no asynchronous features. So, in some complex scenarios, for example, scheduled tasks, such as HTTP and other delayed tasks, must be solved by asynchrony, so, js host browser must assume this responsibility, asynchrony arises at the right moment.

What is asynchrony

As we know, JS is a single thread, in a code block (i.e. a script tag) js line by line execution, if an error occurs, the code block stops execution, but does not affect the other code blocks, if asynchronous task, delay, become a callback function, execution, at this point, we should know that the so-called, Asynchrony in our browser is essentially a delayed callback. To implement this callback, use the browser eventLoop.

eventloop

Eventloop is an execution model, which is a concept that can be implemented differently in different places. For example, node and browser implementations of Eventloop are different, and the execution effect is different. For example:

The same code is displayed in the same order on the browser side

Since today’s topic is browsers, we’ll start with the eventloop in the browser. If you’re interested in Node, go aheadWhat’s the difference between browser and Node Event loopsBefore we get started, let’s talk about some concepts

The Stack (Stack)

This was explained in HTML parsing above.

In computer science, a stack is a linear table that is limited to insert or delete operations at the end of the table. A stack is a data structure that stores data according to the principle of last in, first out. The data entered first is pushed to the bottom of the stack, and the last data is placed at the top of the stack. When data needs to be read, the data will be ejected from the top of the stack. A stack is a special linear table that can only be inserted and deleted at one end.Copy the code

Queue

The special thing is that it only allows deleting at the front end of the table and inserting at the rear end of the table. Like stacks, queues are linear tables with limited operations. The end that inserts is called the end of the queue, and the end that deletes is called the head of the queue. A queue with no elements is called an empty queue. The data elements of a queue are also called queue elements. Inserting a queue element into a queue is called enqueueing, and removing a queue element from a queue is called enqueueing. A queue is called FIFO - first in first out (FIFO - first in first out) because only the earliest element to enter the queue can be deleted from the queue.Copy the code

Macro and micro tasks

Macro tasks: setTimeout, setInterval, setImmediate Ajax and DOM events

Microtasks: process. nextTick (Node only), Promise, async/await, etc

Ok, let’s start the official eventloop with the first imageSo that’s the flow chart of an eventloop, so how do we parse it? Let’s take a browser click.

  • 1. First open the eventloop mechanism of the page to start
  • 2. Then the JS parsing engine starts to execute the JS code
  • 3, meet the binding click thing, the event binding
  • 4. Click the event and push the event callback to the macro task queue. The EventLoop mechanism detects the task that needs to be executed and pushes the JS execution stack to execute it

Now it’s clear how the browser can implement asyncism, and not only asyncism can be implemented with EventLoop, but also events. Why is there a distinction between micro and macro tasks

To understand the distinction between macro tasks and microtasks, we need to first understand the relationship between DOM rendering and eventloop. First, we know that JS execution and browser DOM rendering are mutually exclusive. Therefore, after JS execution, the browser will first execute the microtasks in JS execution and then try to execute DOM rendering. The eventloop mechanism is triggered when the next task is completed, i.e. the eventloop is triggered after the JS synchronization code is executed and after the DOM rendering

Then the eventLoop is executed one by one, then the microtask is put into the microtask queue, then the macro task is put into the macro task queue, and then the eventloop is started again, and so on and so on. So why is the macro task after dom rendering and the microtask before DOM rendering?

Searching through the data, I understand that the reason why there is a distinction between microtasks and macro tasks is that microtasks like Promise are es specifications, not browser specifications, and settiemout is browser API specifications. At this point, the reason why is clear. Because microtasks are ES specifications, even asynchronous, It is also handled by JS parsing, so it is not counted after the eventloop starts

Browser events

To understand the browser’s event mechanism, we need to take a look at some history

Events in history

We know that our input device, called the Pointer device, which is a WIMP is an important part of the paradigm of interfaces that graphical computers use

WIMP

Originally developed by Xerox and later copied by Windows and the MAC, WIMP is the most popular computer interface in the field of human-computer interaction. It has no rival to Microsoft’s Windows, Apple’s MacOS, and even other operating systems based on X Windows. All use WIMP this interface model. WIMP stands for “Window,” “Icon,” “Menu” and “Pointing Device,” and the way it’s named points to the four interacting elements it relies on. (Excerpted from Baidu Encyclopedia, as well as a book by Dr. Wu Jun at the top of the Wave, which specifically talks about how Apple and Microsoft copy the results of Xerox Lab, if you are interested, you can have a look)

WIMP interface model, allowing the operating system in use today, so that today many front-end engineer will have an opinion, think that we can “click a button”, in fact is not the case, we are only able to click on the button on the mouse or touch screen, is the operating system and browser the information corresponding to a button on the logic, And make its view react to click events. This brings us to our first mechanism: capture and bubbling.

Bubble and capture

We all know that the capture process is from the outside in and the bubble process is from the inside out, but why does he do that?

In the above input devices, we take the mouse to click event, for example, when the mouse to click, in fact, is the operating system will we click the operation, the corresponding into a coordinate, returned to the browser, the browser he received coordinates corresponding to a specific I click on which elements, we found that this process is actually the outside-in, This is my understanding of the capture process (in fact, is the big guy understand, I see), and bubbling, is more easy to understand, for example, we in life with the hand to point an item on the table, is it also equivalent to point the table! It is a typical person’s logical thinking has been applied on the computer, and we are in an element is actually we capture and binding events in the history of the process of bubble, listening class we trigger action, to do something, that is to say, as long as you have corresponding action in the input device, no matter whether you listen, capture the bubbling proceed as usual.

To sum it up, capture is the logic of computer events, while bubbling is the logic of human events.

The event

By understanding bubbling and capturing, we know that browser events are the things that our input device listens for while bubbling,

The exact number is not listed if you are interested please go to the browser event summary

In addition to the events provided by our browser, we can also customize events, but they can’t be triggered by the interaction, we have to trigger them manually in the code! It’s very simple to use

Var evt = new Event("look", {"bubbles":true, "cancelable":false}); // Manually triggered event document.dispatchEvent(evT);Copy the code

Browser garbage collection mechanism

To understand the browser’s garbage collection mechanism, we need to understand some terms

  • Reference counting: when an object is not referenced by another object, it is reclaimed
  • Memory leak: Memory that is no longer needed is not released in time
  • Mark-sweep: Periodically marks accessible objects, starting with the root element, and reclaims unreachable objects
  • Cenozoic – Old generation: Objects of the Cenozoic generation are objects with a short lifetime, and objects of the old generation are objects with long lifetime events or permanent memory.

Principles of Garbage Collection

**javascript garbage collection mechanism how it works: The garbage collection mechanism periodically (periodically) finds memory (variables) that are no longer needed and then frees it. There are two common methods of garbage collection in major browsers: tag scavenging and reference counting. ** Reference counting can cause memory to never be free when it comes to circular references, so most browsers now use the tag cleanup method, but each implementation has a slightly different approach and strategy

Each browser takes a different approach, but let’s take Google’s V8 engine as an example

V8’s garbage collection mechanism is divided into the new generation and the old generation.

The Exploitoring is implemented primarily through the Use of Scavenge. The Cheney algorithm is used To evenly split memory into two parts, the use space is called From and the idle space is called To. New objects are allocated To the From space, surviving objects are copied To the From space when the space is almost full, and then the From space is emptied. Swapping From space and To space continues memory allocation, and objects are promoted From the new generation To the old generation when those two conditions are met.

The old generation mainly adopts Mark-sweep and Mark-Compact algorithms, one is Mark Sweep and the other is Mark tidy. The difference between mark-Sweep and Mark-Compact is that after garbage collection, mark-Sweep generates fragmented memory, whereas mark-Compact does a cleanup before cleaning, moving living objects to one side and then empting memory on the other side of the boundary, so that the free memory is continuous, but the problem is that it is slower. In V8, old generation is managed jointly by both Mark-sweep and Mark-Compact. (Quote from the big guy)

Memory leaks

Memory leak refers to the fact that the dynamically allocated heap memory in the program is not released or cannot be released due to some reason, resulting in the waste of system memory, slowing down the running speed of the program and even system crash.Copy the code

To put it bluntly, a memory leak is when variables that you don’t need (or can’t access) still occupy memory space and can’t be reused. It causes some performance problems. In my understanding, only when there are performance problems or hidden problems, it can be judged as a memory leak, rather than I have several variables that are not released

So what exactly are the operations that might cause a memory leak?

1. Unexpected global variables

Such as this

function foo(arg) { bar = "aaaaa"; } function foo(arg) {window.bar = "aaaaa"; }Copy the code

2. Stealth timers

Speak of the timer, cause memory leaks, I met a problem in vue program at the time, in a page with a timer, when switching page, does not destroy, and when switched back to perform before a timer and timer, will be in memory, cause the page more and more CARDS, memory leaks

* * some dom reference each other, not standardize the use of plug-ins (such as I use g2 destroy components before there is no cancellation, lead to memory leaks) * * would not be in here, ok now I know it can cause memory leaks are listed here (if you have more, please bosses told), can not find memory leaks browser itself, It’s the wrong programming.

Whether closures cause memory leaks

After inquiring a lot of information and asking a lot of people, the answer is no. However, it has been widely circulated that closures will cause memory leaks and cause pages to freeze. In fact, it is because of the early garbage collection mechanism of Internet Explorer, there are bugs

  • After using a closure in Internet Explorer, variables referenced in the closure cannot be reclaimed.
  • In Internet explorer, objects in BOM and DOM are implemented as COM objects using C++, and the garbage collection mechanism of COM objects adopts reference counting strategy. In a garbage collection mechanism based on a reference counting strategy, if a circular reference is formed between two objects, neither object can be reclaimed, but memory leaks caused by circular references are not caused by closures per se.

And we have a lot of people, will memory usage and memory leaks and confuse, don’t think some of memory used variables are memory leaks, in fact, in a modern browser, if you are not the cycle of fault generated a lot of closure, in general, will not have a memory leak, of course, you generate a lot of closures, also have nothing to do with memory leaks, There’s something wrong with your programming.

Next is a more controversial problem, checked the little Red book, a lot of data, do not have the exact answer, if there is big guy know, hope to inform: attach the answer of the big guys

Pro:Against:Can a variable stored in a closure be released after it is used?

Why caching is an important tool for performance optimization

Speaking of the browser cache, the first thing we think of the performance problems, online everywhere every day to discuss the performance problems, and interview performance is also quite popular, what open gzip, lazy loading images, DNS resolution beforehand, and so on, give me the feeling of for caching of the user experience, indeed, but the cache also has a fatal weakness, It doesn’t cache the first time it’s loaded, so it’s still pretty good the first time it’s loaded.

There are also some performance optimizations in the code, such as, is it better to store data as a unique key object or as an array? For example, is it faster to use the index of an array, or is it faster to use the key of an object, or is for-in very performance-intensive, etc. In my opinion, it doesn’t do anything except make you feel tangled when writing code, or have something to talk about when checking your company code.

The lesson I’ve learned so far is that, with the exception of those performance-consuming issues that need to be avoided when necessary (such as deep recursion), it’s all about writing less maintainable code

Browser to Cache

The summary about browser caching is pretty good:Have an in-depth understanding of the browser caching mechanism

To conclude, browsers are divided into strong and negotiated caches. Mandated caches take precedence over negotiated caches. If mandated caches (Expires and cache-control) are in effect, they are used directly. If it does not take effect, the negotiation cache (last-modified/if-modified-since and Etag/if-none-match) is carried out. The negotiation cache is determined by the server whether to use the cache. If the negotiation cache is invalid, then the cache of the request is invalid and the request result is obtained again. Store it in the browser cache; If it takes effect, return to 304 and continue to use the cache. The next illustration explains:

Therefore, due to this mechanism of the browser, we can quickly get resources from the memory or hard disk and render the page, greatly improving the user experience. However, when using the cache, we need to pay attention to the following:

  • If the server file is updated, the file name must be changed, otherwise the cache time may not be invalid and the page will not be requested (of course, now the scaffolding has been done for us).
  • The get interface may be cached, so if the CDN is set for the whole site, be careful to force the CDN to change the default cache policy when returning
  • In today’s spa project popular, index page may also be cached, so to be safe, index page can be added to the mate header, of course, under normal circumstances, the server will default to this file is not cached, but it is not guaranteed

The last

Lasted for two weeks, off and on finally finished writing, oneself also have a deeper understanding to the browser, also checked a lot of information (if need red book, big rhinoceros and other e-books, please private letter), if have wrong place please big guy to give directions! In the future, please look forward to re-learning the front-end series

Attached: Working from home – Learning front (1)

Relearn front-end (2)- Do you really know your JS object?