Recently, I have arranged the high frequency test questions on the front face and shared them with you to learn. If you have any questions, please correct me!

Note: 2021.5.21 has been updated to modify some errors in this article. Add a mind map, according to their own interview experience and the interview on the platform such as Niuker.com, the frequency of the interview questions will be roughly divided, can be targeted to review.

The following is a series of articles.

[1] “2021” high frequency front face test summary HTML article

[2] “2021” high-frequency front end of the CSS section

[3] 2021

[4] 2021

[5] “2021”

[6] “2021”

【7】 “2021” High-Frequency front end test questions summary

[8] “2021” high frequency front end test questions summary

[9] “2021” high frequency front end test question summary of computer network article

[10] “2021” high frequency front end test summary of browser principles

[11] the performance optimization of “2021” high frequency test paper summary

[12] “2021” high frequency front end of the handwritten code of the test summary

[13] “2021” high frequency front end test summary code output results

First, browser security

1. What are XSS attacks?

(1) Concept

An XSS attack refers to a cross-site scripting attack, which is a code injection attack. By injecting malicious scripts into websites that run on users’ browsers, attackers can steal users’ information, such as cookies.

The essence of XSS is that the malicious code is not filtered by the website and is mixed with the normal code. The browser has no way to tell which scripts are trustworthy, resulting in the execution of the malicious code.

An attacker can perform the following operations in this attack mode:

  • Obtain page data, such as DOM, cookie, localStorage;
  • DOS attack, sending reasonable requests, occupying server resources, so that users can not access the server;
  • Destroy page structure;
  • Traffic hijacking (linking to a website);

(2) Attack type

XSS can be divided into storage, reflection and DOM types:

  • Stored means that the malicious script is stored on the target server, and when the browser requests the data, the script is passed back from the server and executed.
  • Reflection refers to that after the attacker induces the user to access a URL with malicious code, the server side receives the data and processes it, and then sends the data with malicious code to the browser side. The browser side parses the data with XSS code and executes it as a script, and finally completes the XSS attack.
  • DOM type refers to XSS formed by modifying the DOM nodes of the page.

1) Attack steps of storage XSS:

  1. The attacker submits the malicious code to the target site’s database.
  2. When the user opens the target site, the server pulls the malicious code out of the database and returns it to the browser in HTML.
  3. The user’s browser receives the response, parses it and executes the malicious code mixed in.
  4. Malicious code steals user data and sends it to the attacker’s website, or impersonates a user to invoke the target website interface to perform operations specified by the attacker.

Such attacks are common on web features with user saved data, such as forum posts, product reviews, and private messages.

2) Attack steps of reflective XSS:

  1. Attackers construct special urls that contain malicious code.
  2. When a user opens a URL with malicious code, the web server takes the malicious code out of the URL and returns it to the browser in HTML.
  3. The user’s browser receives the response, parses it and executes the malicious code mixed in.
  4. Malicious code steals user data and sends it to the attacker’s website, or impersonates a user to invoke the target website interface to perform operations specified by the attacker.

The difference between reflected XSS and stored XSS is that the malicious code of stored XSS is stored in the database, while the malicious code of reflected XSS is stored in the URL.

Reflective XSS vulnerabilities are commonly found in functions that pass parameters through urls, such as website search, jump, and so on. Because the user needs to open the malicious URL to take effect, the attacker will often use a variety of methods to induce the user to click.

3) DOM XSS attack steps:

  1. Attackers construct special urls that contain malicious code.
  2. The user opens a URL with malicious code.
  3. The user’s browser receives the response, parses it and executes it. The front-end JavaScript pulls out the malicious code in the URL and executes it.
  4. Malicious code steals user data and sends it to the attacker’s website, or impersonates a user to invoke the target website interface to perform operations specified by the attacker.

DOM XSS is different from the previous two XSS: In DOM XSS attack, the extraction and execution of malicious code is done by the browser side, which is a security vulnerability of the front-end JavaScript itself, while the other two XSS are security vulnerabilities of the server side.

2. How to defend against XSS attacks?

You can see that XSS is so harmful, so in the development of the website should do a good job of defense measures, specific measures are as follows:

  • This can be prevented by the browser’s execution. One way is to use a purely front-end approach, without server-side splicing and returning (without server-side rendering). The other is to adequately escape the code that needs to be inserted into the HTML. DOM type attacks are mainly caused by the unreliability of the front end script. For data acquisition rendering and string concatenation, the possible malicious code situation should be judged.
  • With CSP, the essence of CSP is to create a whitelist that tells the browser what external resources can be loaded and executed, thus preventing the injection of malicious code.
  1. CSP stands for content security policy, which essentially creates a whitelist that tells browsers what external resources can be loaded and executed. We just need to configure the rules, and it’s up to the browser to do that.
  2. There are two ways to enable CSP: setting content-security-policy in the HTTP header and setting meta tags
  • Protect some sensitive information, such as cookies using HTTP-only, so that the script cannot obtain them. You can also use a verification code to prevent the script from pretending to be the user to perform some operations.

3. What is a CSRF attack?

(1) Concept

A CSRF attack is a cross-site request forgery attack in which an attacker directs a user to a third-party site that then sends cross-site requests to the attacked site. If the user saves the login status in the attacked site, the attacker can use this login status to bypass the background user authentication and impersonate the user to perform some operations to the server.

The essence of CSRF attack is to use the cookie to carry the characteristics of sending to the server in the same origin request, so as to realize the impersonation of users.

(2) Attack type

There are three common CSRF attacks:

  • GET type CSRF attacks, such as building a request in an IMG tag on a website, automatically initiate a submission when the user opens the site.
  • POST type CSRF attacks, such as building a form, then hiding it, and automatically submitting the form when the user enters the page.
  • Link type CSRF attacks, such as building a request in the a tag’s href attribute, and then inducing the user to click.

4. How do I defend against CSRF attacks?

CSRF attacks can be protected by the following methods:

  • The server determines whether the request is an accessible site based on the origin or referer information in the HTTP request header and filters the request. If the Origin or referer information does not exist, the request is blocked. The downside of this approach is that referer can be falsified in some cases and can also block links to search engines. So the general website will allow the search engine page request, but the corresponding page request this request method may also be used by attackers. (The Referer field tells the server which page the page was linked from.)
  • The CSRF Token is used for authentication, and the server returns a random number Token to the user. When the website initiates a request again, the Token returned by the server is added to the request parameters, and then the server verifies the Token. This method solves the problem that it may be used fraudently when using cookie single authentication method, but this method has a disadvantage that we need to add this token to all requests in the website, which makes the operation more tedious. Another problem is that there is usually more than one web server. If the request is load-balanced to another server, but the server’s session does not retain the token, there is no way to verify it. This situation can be addressed by changing the way tokens are constructed.
  • Double authentication is performed for cookies. When the user visits the website page, the server injects a Cookie with a random string into the request domain name. Then, when the user sends a request to the server again, it takes out this string from the Cookie and adds it to the URL parameter. The server then verifies by comparing the data in the cookie with the data in the parameter. Using this method is to take advantage of the attacker can only use the cookie, but can not access the cookie characteristics. And this method is more convenient than the CSRF Token method, and does not involve the problem of distributed access. The downside of this approach is that it will be ineffective if the site has XSS vulnerabilities. In addition, sub-domain names cannot be isolated in this way.
  • Set Samesite when setting cookie attributes to prevent cookies from being used by third parties, so as to avoid being exploited by attackers. Samesite has two modes. One is strict mode. In strict mode, cookies cannot be used as third-party cookies under any circumstances; in loose mode, cookies can be used by requests that are GET requests and page hops.

What is a man-in-the-middle attack? How to prevent man-in-the-middle attacks?

Man-in-the-middle Attack (MITM) is when an attacker creates an independent connection with each end of the communication and exchanges the data they receive, making the two ends of the communication think they are talking directly to each other through a private connection, but in fact the entire conversation is completely controlled by the attacker. In a man-in-the-middle attack, an attacker can intercept calls between two parties and insert new content.

The attack process is as follows:

  • The client sends a request to the server. The request is intercepted by a middleman
  • The server sends the public key to the client
  • The middleman intercepts the public key and keeps it. Then generate a forged public key and send it to the client
  • After receiving the forged public key, the client generates an encrypted hash value and sends it to the server
  • The middleman obtains the encrypted hash value, decrypts it with his private key to obtain the real key, and generates a fake encrypted hash value to send to the server
  • The server decrypts the fake key with the private key, then encrypts the data and transmits it to the client

6. What are the potential front-end security issues?

  • Cross-site Scripting (XSS): A method of code injection, called XSS to distinguish it from CSS. In the early days, it was commonly used in online forums. The reason was that the website did not impose strict restrictions on user input, which allowed attackers to upload scripts to posts and let others browse to pages with malicious scripts. The injection methods were very simple, including but not limited to JavaScript/CSS/Flash, etc.
  • Abuse of iframe: The content in the iframe is provided by third parties. By default, they are not controlled. They can run JavaScirpt scripts, Flash plug-ins, pop-up dialog boxes and so on in the iframe, which may destroy the front-end user experience.
  • Cross-site Request Forgeries (CSRF) : An attacker forces an authenticated user to update his or her status with unexpected personal information or setting information through a set trap, which is a passive attack
  • Malicious third-party libraries: Whether back-end server applications or front-end application development, most of the time is in the development framework and a variety of class libraries for rapid development, once the third-party library is implanted with malicious code is easy to cause security problems.

7. What are the types of network hijacking and how to prevent it?

There are two types of hijack:

(1) DNS hijacking: (enter jd is forced to jump to Taobao, which belongs to DNS hijacking)

  • DNS forced resolution: Changes the local DNS records of the carrier to direct user traffic to the cache server
  • 302 hops: Monitors the traffic at the network egress, analyzes the content that can be hijacked, and sends a 302 hops reply to the hijacked memory to guide users to obtain the content

(2) HTTP hijacking: (visit Google but have been playing blue Moon ads), due to HTTP plaintext transmission, the carrier will modify your HTTP response (i.e. add ads)

DNS hijacking has been regulated because it is suspected of being illegal. There is very little DNS hijacking nowadays, but HTTP hijacking is still very prevalent. The most effective method is to use full-site HTTPS.

Processes and threads

1. Concepts of processes and threads

Essentially, processes and threads are a description of the CPU’s time slice:

  • A process describes how long it takes the CPU to run instructions and load and save the context. In the case of an application, a process represents a program.
  • Threads are smaller units in a process that describe the time it takes to execute a single instruction.

A process is the smallest unit of resource allocation, and a thread is the smallest unit of CPU scheduling.

A process is a running instance of a program. In detail, when a program is started, the operating system creates a block of memory for the program to hold the code, the running data, and a main thread to perform the task. We call such a run environment a process. Processes run on virtual memory, which is used to solve the contradiction between users’ unlimited demand for hardware resources and limited hardware resources. From an operating system perspective, virtual memory is a swap file; From the processor’s perspective, virtual memory is the virtual address space.

If a lot of programs, memory may be insufficient, the operating system for each process to provide a set of independent virtual address space, so that the same physical there are different processes can correspond to different or the same virtual address, in a disguised increase in the program can use memory.

The relationship between processes and threads has the following four characteristics:

(1) In the process of any thread execution error, will lead to the entire process crash.

(2) Sharing process data between threads.

(3) When a process is shut down, the operating system will reclaim the memory occupied by the process; when a process exits, the operating system will reclaim all the resources applied by the process; Even if any of the threads leak memory due to misoperation, when the process exits, the memory is properly reclaimed.

(4) The content between processes is isolated from each other. Process isolation is to ensure that processes in the operating system do not interfere with each other. Each process can only access its own data, which prevents process A from writing data to process B. Because data is strictly isolated from each other, a process that crashes or hangs does not affect other processes. If data needs to be communicated between processes, then the mechanism for inter-process communication needs to be used.

Architecture of the Chrome browser:As you can see, the latest Chrome browsers include:

  • 1 browser main process
  • One GPU process
  • 1 network process
  • Multiple rendering processes
  • Multiple plug-in processes

The functions of these processes:

  • Browser process: mainly responsible for interface display, user interaction, child process management, and storage functions.
  • Rendering process: The core task is to convert HTML, CSS, and JavaScript into web pages that users can interact with. Both the typographical engine Blink and the JavaScript engine V8 run in this process. By default, Chrome creates a rendering process for each Tab. For security reasons, rendering processes are run in sandbox mode.
  • GPU process: In fact, the original purpose of GPU is to achieve the effect of 3D CSS, but later web pages, Chrome UI interface is chosen to use GPU to draw, which makes GPU become a common demand of browsers. Finally, Chrome introduces GPU processes on top of its multi-process architecture.
  • Network process: It is responsible for loading network resources of the page. It used to run as a module in the browser process, until recently it became a separate process.
  • Plug-in process: It is mainly responsible for the running of plug-ins. Because plug-ins are prone to crash, you need to isolate them by plug-in process to ensure that the crash of plug-in process does not affect browsers and pages.

Therefore, to open a web page, you need at least four processes: one network process, one browser process, one GPU process, and one rendering process. If the open page has a plugin running, you need to add another plugin process.

While the multi-process model improves browser stability, fluency, and security, it also inevitably brings some problems:

  • Higher resource consumption: Because each process contains a copy of the common infrastructure (such as the JavaScript runtime environment), this means that the browser consumes more memory resources.
  • More complex architectures: High coupling between browser modules and poor scalability can make it difficult for existing architectures to adapt to new requirements.

2. Differences between processes and threads

  • Processes can be treated as standalone applications; threads cannot
  • Resource: A process is the smallest unit of CPU resources allocated (it is the smallest unit that can hold resources and run independently). A thread is the minimum unit of CPU scheduling (a thread is a unit of program running at a time based on a process, a process can have more than one thread).
  • Communication: Threads can directly share resources in the same process, while process communication requires inter-process communication.
  • Scheduling: Process switching is more expensive than thread switching. Threads are the basic unit of CPU scheduling. A thread switch does not cause a process switch, but a process switch will occur when a thread in one process switches to a thread in another process.
  • System overhead: Since the system allocates or reclaims resources such as memory, I/O, etc., when creating or destroying a process, the overhead is much greater than when creating or destroying a thread. Similarly, during the process switch, the CPU environment of the current executing process and the saving of various states and the setting of the new scheduling process state are involved, while the thread switch only needs to save and set a small number of register contents, which is less costly.

3. What are the threads of the browser rendering process

The browser’s render process has five threads:(1) GUI rendering threadResponsible for rendering browser pages, parsing HTML, CSS, building DOM trees, building CSSOM trees, building render trees and drawing pages; When the interface requiresredrawOr by some operationbackflow, the thread executes.

Note: The GUI rendering thread and THE JS engine thread are mutually exclusive, the GUI thread is suspended while the JS engine is executing, and GUI updates are kept in a queue until the JS engine is idle and executed immediately.

(2) JS engine thread, also known as JS kernel, is responsible for processing Javascript scripts, parsing Javascript scripts, and running code; The JS engine thread has been waiting for the arrival of tasks in the task queue, and then to deal with, a Tab page at any time only a JS engine thread is running JS program;

Note: The GUI rendering thread is mutually exclusive with the JS engine thread, so if the EXECUTION of JS takes too long, the rendering of the page will be incoherent and the page rendering load will be blocked.

(3) Time-triggered thread The time-triggered thread belongs to the browser rather than the JS engine and is used to control the event loop; 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.), the corresponding task is added to the event-triggered thread. When the corresponding event is triggered according to the triggering conditions, the thread will add the event to the end of the queue to be processed, waiting for the JS engine processing;

Note: Due to the single-threaded nature of JS, these events in the queue are queued for the JS engine to process (when the JS engine is idle).

(4) Timer triggering process Timer triggering process is the thread where setInterval and setTimeout reside; The browser timing counter is not counted by the JS engine, because the JS engine is single-threaded, and 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 timer. After the timer is finished, it is added to the event queue and executed after the JS engine is idle. Therefore, the tasks in the timer may not be executed on time at the set time point, but the timer only adds the tasks to the event queue at the specified time point.

Note: In the HTML standard, the W3C states that the timer time must not be less than 4ms, if it is less than 4ms, the default is 4ms.

(5) Asynchronous HTTP request threads

  • XMLHttpRequest after the connection through the browser opened a new thread request;
  • When the state change is detected, if the callback function is set, the asynchronous thread will produce the state change event, put the callback function into the event queue, and wait for the execution after the JS engine is idle;

4. Previous communication mode of the process

(1) Pipeline communication

A pipeline is one of the most basic interprocess communication mechanisms. A pipeline is a buffer created in the kernel by the operating system. Process 1 can copy the data to this buffer and process 2 can read it.

Characteristics of the pipeline:

  • Only one-way communication
  • Only blood processes can communicate
  • It depends on the file system
  • The life cycle follows the process
  • Byte stream oriented services
  • A synchronization mechanism is provided within the pipeline

(2) Message queue communication

A message queue is just a list of messages. Users can add messages to the message queue, read messages, and so on. Message queues provide a way to send a block of data from one process to another. Each data block is considered to contain a type, and the receiving process can independently receive data structures containing different types. You can avoid synchronization and blocking problems with named pipes by sending messages. But message queues, like named pipes, have a maximum length limit for each data block.

Using message queue for inter-process communication may result in the restriction of the maximum length of data block, which is also the disadvantage of this communication mode. If interprocess communication behavior occurs frequently, then the process needs to read the data from the queue to memory frequently, which is equivalent to indirectly copying from one process to another process, which takes time.

(3) Semaphore communication

One of the biggest problems with shared memory is the problem of multiple processes competing for memory, similar to thread-safety issues. We can use semaphores to solve this problem. The semaphore is essentially a counter used to keep processes mutually exclusive and synchronized. For example, if the initial value of the semaphore is 1, and if process A tries to access memory 1, we set the semaphore to 0, and if process B tries to access memory 1, we see that the semaphore is 0, so that process B can’t access memory 1. So, semaphores are also a means of communication between processes.

(4) Signal communication

Signals are one of the oldest methods of interprocess communication used on Unix systems. The operating system uses signals to notify processes that a predetermined event (one of a set of events) has occurred in the system, and it is an original mechanism for communication and synchronization between user processes.

(5) Shared memory communication

Shared memory is a map of memory that can be accessed by other processes. This shared memory is created by one process but can be accessed by multiple processes (allowing multiple processes to access the same memory space). Shared memory is the fastest IPC method, and it is specially designed for the inefficiency of other inter-process communication methods. It is often used in conjunction with other communication mechanisms, such as semaphores, to achieve synchronization and communication between processes.

(6) Socket communication

Shared memory, pipes, semaphores, message queues are all processes communicating on a single host. Can two processes thousands of miles apart communicate? Answer is necessary, this time Socket this guy will come in handy, for example, we usually through the browser to initiate an HTTP request, and then the server to return to you the corresponding data, this is the use of Socket communication mode.

5. What are zombie processes and orphan processes?

  • Orphaned processes: If a parent exits and one or more of its processes are still running, these processes are orphaned. The orphan processes will be adopted by the init process (process number 1), and the init process will do the state collection on them.
  • Zombie: A zombie process is a process in which the child process terminates before the parent process, and the parent process does not release the resources occupied by the child process, so the child process’s process descriptor remains in the system.

6. What causes the deadlock? How to solve the deadlock problem?

Deadlock refers to a deadlock caused by multiple processes competing for resources in the process of running. When a process is in this deadlock state, it will not be able to move forward without external force.

Resources in the system can be divided into two categories:

  • Deprived resources mean that after a process obtains such resources, the resources can be deprived by other processes or systems. Both CPU and main memory are deprived resources.
  • Inalienable resources. After allocating resources to a process, the system can only release resources after the process is used up. For example, a tape drive or a printer.

Causes of deadlock:

(1) Competition for resources

  • One of the competing resources in deadlock generation refers to the competing inalienable resources (for example, there is only one printer on the system available to process P1, assuming P1 has occupied the printer, and P2 will block if it continues to ask the printer to print).
  • Contending resources in deadlock Another type of resource is contending temporary resources (such as hardware interrupts, signals, messages, messages in buffers, etc.), which are usually communicated in the wrong order, resulting in deadlock

(2) The sequence of inter-process advancement is illegal

If P1 holds resource R1 and P2 holds resource R2, the system is in an unsafe state because deadlocks can occur if the two processes move forward. For example, when P1 runs on P1: Request (R2), it will block because R2 is already occupied by P2. When P2 runs on P2: Request (R1), it will also block because R1 is already occupied by P1, resulting in a process deadlock

The necessary conditions for creating a deadlock are:

  • Mutual exclusion: Processes require exclusive control over allocated resources. That is, only one process can use a certain resource for a certain period of time.
  • Request and hold conditions: When a process is blocked by a request for a resource, it holds a resource that has been obtained.
  • Non-deprivation condition: The process cannot deprive the resources it has obtained before using them, and can only release them by itself when they are used up.
  • Loop wait condition: When a deadlock occurs, there must be a loop chain of process-resources.

Ways to prevent deadlocks:

  • Resource allocation: Allocate all resources at once so that no more requests are made (breaking the request condition)
  • As long as a resource is not allocated, no other resource is allocated to the process.
  • Deprivable resources: When a process gets some resources but does not get others, it releases the resources it already owns (breaking the inalienable condition)
  • Orderly resource allocation method: The system assigns a number to each type of resource, and each process requests resources in the ascending order of the number. Releasing resources is the opposite (destroy the loop waiting condition).

7. How to communicate between multiple tabs in a browser?

Communication between multiple tabs is achieved through the intermediary pattern in essence. Since there is no way for the tabs to communicate directly with each other, we can find an intermediary, have the tabs communicate with the intermediary, and then have the intermediary forward the message. The communication method is as follows:

  • Use the WebSocket protocol, because the WebSocket protocol implements server push, so the server can be used as the intermediary. Tabs send data to the server, which then pushes and forwards the data to other tabs.
  • With ShareWorker, a unique thread is created for the lifetime of the page, and only one thread is used when multiple pages are opened. At this point the shared thread can act as an intermediary. Tabs share a thread, and then exchange data through this shared thread.
  • Using localStorage, we can listen for localStorage changes in one TAB, and then when another TAB changes data, we can get the data through this listener event. In this case, the localStorage object acts as the intermediary.
  • Using the postMessage method, if we can get a reference to the corresponding TAB, we can use the postMessage method to communicate.

8. Understanding of Service workers

A Service Worker is a separate thread that runs behind the browser and is typically used to implement caching. To use a Service Worker, the transport protocol must be HTTPS. Because request interception is involved in the Service Worker, the HTTPS protocol must be used for security.

Service workers generally implement caching in three steps: First of all, you need to register the Service Worker, and then after listening to the install event, you can cache the required files, so the next time the user visits, you can check whether there is a cache by intercepting the request. If there is a cache, you can directly read the cache file, otherwise you can request the data. Here is the implementation of this step:

// index.js
if (navigator.serviceWorker) {
  navigator.serviceWorker
    .register('sw.js')
    .then(function(registration) {
      console.log('Service worker registered successfully')
    })
    .catch(function(err) {
      console.log('Servcie worker registration failed')})}// sw.js
// Listen for 'install' events and cache the required files in the callback
self.addEventListener('install'.e= > {
  e.waitUntil(
    caches.open('my-cache').then(function(cache) {
      return cache.addAll(['./index.html'.'./index.js'])}})))// Intercept all request events
// If the requested data is already in the cache, use the cache, otherwise request the data
self.addEventListener('fetch'.e= > {
  e.respondWith(
    caches.match(e.request).then(function(response) {
      if (response) {
        return response
      }
      console.log('fetch source')}})))Copy the code

Open the page available in developer ToolsApplicationSee that the Service Worker is already started:You can also find that the required file has been cached in Cache:

3. Browser cache

1. Understand the caching mechanism of browsers

The whole process of browser caching:

  • When the browser loads the resource for the first time, the server returns 200. The browser downloads the resource file from the server and caches the resource file and response header for comparison in the next loading.
  • When the resource is loaded next time, the mandatory cache priority is higher. The time difference between the current time and the last time when 200 is returned is first compared. If the time difference does not exceed the max-age set by cache-control, the resource is not expired, hits the strong cache, and directly reads the resource from the local. If the browser does not support HTTP1.1, the Expires header is used to determine whether it is expired.
  • If the resource is expired, it indicates that the mandatory cache has not been hit, and the cache is negotiated, sending a request to the server with if-none-match and if-modified-since;
  • After receiving the request, the server determines whether the requested file is modified according to the Etag value. If the Etag value is the same, the file is not modified. The negotiated cache is matched and 304 is returned. If not, return the new resource file with the new Etag value and return 200.
  • If the server receives a request with no Etag value, the if-modified-since is compared to the last Modified time of the requested file. If it matches the negotiated cache, 304 is returned. If not, return the new last-modified file and 200;

Many website resources are added after the version number, the purpose of this is: every time after the UPGRADE of JS or CSS file, in order to prevent the browser to cache, forced to change the version number, the client browser will download a new JS or CSS file, to ensure that users can get the latest website updates in a timely manner.

2. Where are browser resources cached?

There are three locations for the resource cache, which are in descending order of priority:

  1. Service Worker: The Service Worker runs outside the main JavaScript thread. Although the Service Worker cannot directly access the DOM because it is separated from the browser form, it can perform functions such as offline caching, message push, network proxy, etc. It gives us the freedom to control which files are cached, how the cache is matched, how the cache is read, and that the cache is persistent. When the Service Worker does not hit the cache, the fetch function needs to be called to fetch the data. In other words, if the cache is not hit by the Service Worker, the data will be searched according to the cache lookup priority. However, whether the data is retrieved from the Memory Cache or from a network request, the browser will display the data retrieved from the Service Worker.

  2. Memory Cache: Memory Cache is the most efficient Cache, ** but Memory Cache is more efficient, but has a short duration and is released as the process releases. ** Once we close the Tab page, the in-memory cache is freed.

  3. Disk Cache: Disk Cache is a Cache stored on a hard Disk. It is slower to read, but can store everything on Disk. It is better than Memory Cache in terms of capacity and time. ** Disk Cache coverage is basically the largest of all browser caches. It uses the fields in the HTTP Herder to determine which resources need to be cached, which resources can be used without a request, and which resources have expired and need to be rerequested. And even in the case of cross-site, resources at the same address, once cached by the hard disk, will not be asked for data again.

Disk Cache: Push Cache is HTTP/2 and is used only when none of the above three caches is hit. And the cache time is very short, only exists in the Session (Session), once the end of the Session is released. It has the following characteristics:

  • All resources can be pushed, but Edge is not compatible with Safari
  • Can pushno-cacheno-storeThe resources of
  • Once the connection is closed, the Push Cache is released
  • Multiple pages can use the same HTTP/2 connection, which means they can use the same cache
  • The Cache in Push Cache can be used only once
  • The browser can refuse to accept an existing resource push
  • You can push resources to other domains

3. The difference between negotiated cache and strong cache

(1) Strong cache

When the strong caching policy is used, if the cache resources are valid, the cache resources are used directly without sending requests to the server.

A strong caching policy can be set in two ways: the Expires and cache-control attributes in the HTTP header.

(1) The server specifies the expiration time of the resource by adding the Expires attribute in the response header. Within the expiration time, the resource can be cached and used without having to send a request to the server. This time is an absolute time. It is the server time, so there may be problems such as the client time and server time are not consistent, or the user can change the client time, which may affect the cache hit result.

(2) Expires is the way http1.0 is. Because of some of its drawbacks, a new header property introduced in HTTP 1.1 is the cache-control property, which provides more precise Control over how resources are cached. It has a lot of different values,

Cache-control Configurable fields:

  • publicResource representations with this field value set can be cached by any object, including the client sending the request, the proxy server, and so on. This field value is not often used, but is usually controlled precisely using max-age=;
  • private: The resource with this field value can only be cached by the user’s browser, not by any proxy server. In actual development, for some HTML containing user information, it is usually necessary to set this field value, to avoid the proxy server (CDN) cache;
  • no-cache: If this field is set, you need to check with the server whether the returned resource has changed. If the resource has not changed, the cached resource is used.
  • no-store: If this field is set, it indicates that no caching is allowed. Each time, new requests are sent to the server to pull the latest resources.
  • max-age=: Sets the maximum validity period of the cache, in seconds.
  • s-maxage=: has a higher priority than max-age=, which applies only to shared CDN, and has a higher priority than max-age or Expires headers.
  • max-stale[=]: If this field is set, it indicates that the client is willing to receive expired resources, but the specified time limit cannot be exceeded.

Generally, you only need to set one of these methods to implement a strong caching policy, and cache-control takes precedence over Expires when used together.

No-cache and no-store can be confused:

  • No-cache means to check with the server whether resources have been updated. That is, there is no strong cache, but there is a negotiated cache;
  • No-store means that resources are fetched directly from the server on each request without any caching.

(2) Negotiation cache

If the force cache is hit, we don’t need to make a new request. If the force cache is not hit, if the negotiated cache is set, then the negotiated cache will come into play.

As mentioned above, there are two conditions to hit the negotiated cache:

  • max-age=xxxOut of date
  • A value ofno-store

When a negotiated cache policy is used, a request is sent to the server first, and if the resource has not been modified, a 304 state is returned, allowing the browser to use the local cache copy. If the resource has been modified, the modified resource is returned.

The negotiated cache can also be set in two ways, using the Etag and last-Modified properties of the HTTP header.

(1) The server indicates when the resource was Last Modified by adding a last-modified property to the response header. When the browser next makes a request, it adds an if-modified-since property to the request header. The value of the property is the last-modified value of the Last time the resource was returned. When the request is sent to the server, the server uses this property to compare the last time the resource was modified to determine whether the resource has been modified. If the resource is not modified, the 304 state is returned and the client uses the local cache. If the resource has been modified, the modified resource is returned. The disadvantage of using this method is that the last-modified annotation is accurate only to the second level. If a file has been Modified multiple times in less than a second, the file will have changed but the last-modified file will not change, resulting in inaccurate cache hits.

(2) Because of this possible inaccuracy of last-modified, HTTP provides an alternative, the Etag attribute. When the server returns a resource, it adds an Etag attribute to the header. This attribute is the unique identifier generated for the resource, and the value changes as the resource changes. On the next resource request, the browser will add an if-none-match attribute to the request header, the value of which is the value of the Etag of the resource returned last time. After receiving the request, the service compares this value with the current Etag value of the resource to determine whether the resource has changed and whether the resource needs to be returned. In this way, it’s more precise than the last-modified approach.

When last-Modified and Etag attributes are present at the same time, Etag takes precedence. When using a negotiated cache, the server needs to consider load balancing, so the last-Modified properties of resources on multiple servers should be consistent because Etag values are different on each server, so it is best not to set the Etag attribute when considering load balancing.

Conclusion:

Both strong-cache and negotiated cache policies use the local cache copy directly when a cache hit occurs, except that the negotiated cache sends a request to the server once. When they don’t hit the cache, they send a request to the server to get the resource. In the actual caching mechanism, the strong cache policy and the negotiated cache policy are used together. The browser first determines whether the strong cache is hit based on the request information, and if it is hit, the browser directly uses the resource. If no, the server sends a request to the server based on the header information and uses the negotiation cache. If the negotiation cache matches the request, the server does not return resources and the browser directly uses the copy of the local resource. If the negotiation cache does not match the request, the browser returns the latest resource to the browser.

4. Why do you need browser caching?

For browser caching, which mainly targets front-end static resources, the best effect is to pull the corresponding static resources after the request is made and save them locally. If the server’s static resources have not been updated, then in the next request, directly read from the local, if the server’s static resources have been updated, then we request again, to the server to pull new resources, and save in the local. This greatly reduces the number of requests and improves the performance of the site. This is where the browser’s caching strategy comes in.

The so-called browser cache refers to the browser to the user request static resources, stored in the computer local disk, when the browser access again, directly from the local load, do not need to go to the server request.

Using browser caching has the following advantages:

  • Reduce the burden of the server, improve the performance of the website
  • Speed up the loading of client web pages
  • Redundant network data transmission is reduced

5. What’s the difference between hitting the refresh button or pressing F5, Ctrl+F5 (force refresh) and enter in the address bar?

  • Click the refresh button or press F5: the browser will directly expire the local cached file, but with if-modifed-since, if-none-match, which means the server will check the freshness of the file and return either 304 or 200.
  • The user presses Ctrl+F5 (force refresh) : not only will the browser expire the local file, but it will not carry if-modifed-since, if-none-match, which means it has never been requested before and returns 200.
  • Enter in the address bar: The browser makes a request, follows the normal process, locally checks for expiration, then the server checks for freshness, and finally returns the content.

Four, browser composition

1. Understanding the browser

The main function of the browser is to present the web resources selected by the user. It needs to request resources from the server and display them in the browser window. The format of resources is usually HTML, but also includes PDF, Image, and other formats. The user uses the Uniform Resource Identifier (URI) to specify the location of the requested Resource.

The HTML and CSS specifications, which govern how browsers interpret HTML documents, are maintained by the W3C, the organization responsible for developing Web standards. However, browser vendors are developing their own extensions, and their compliance with the specification is not perfect, which brings serious compatibility problems for Web developers.

The browser can be divided into two parts, shell and kernel. Among them, there are more types of shell and less kernel. There are also browsers that do not distinguish between shell and kernel. A clear division between shell and kernel was created when Mozilla separated Gecko.

  • Shell is the shell of a browser: menus, toolbars, etc. It mainly provides user interface operation, parameter setting and so on. It calls the kernel to implement various functions.
  • The kernel is the core of the browser. A kernel is a program or module that displays content in a markup language.

2. Understanding the browser kernel

The browser kernel is divided into two main parts:

  • The rendering engine’s job is to render, which is to display the requested content in the browser window. By default, the rendering engine can display HTML and XML documents and images, but it can also display other types of data with plug-ins, such as the PDF reader plug-in, which can display PDF.
  • JS engine: parses and executes javascript to achieve dynamic effects of web pages.

At first there was no clear distinction between the rendering engine and the JS engine. As the JS engine became more and more independent, the kernel tended to refer only to the rendering engine.

3. Common browser kernel comparisons

  • Trident: It was the Internet Explorer kernel, and it was popular because IT had a lot of market share in the early days, and a lot of web pages were written based on it, but it didn’t really support real web standards very well. However, due to the high market share of Internet Explorer, Microsoft has not updated the Trident kernel for a long time, resulting in a disconnect between the Trident kernel and the W3C standard. A number of security issues, such as bugs in the Trident kernel, have not been resolved, and some experts have made public their views that Internet Explorer is not secure, causing many users to switch to other browsers.
  • Gecko: This is the kernel used by Firefox and Flock. The advantage of this kernel is that it is powerful and rich, and can support a lot of complex web effects and browser extensions, but the obvious cost is that it consumes a lot of resources, such as memory.
  • Presto: Opera used the Presto kernel, which is widely considered to be the fastest kernel for web browsing, thanks to its inherent advantages in development. It is about three times faster than other kernels when dealing with scripting languages such as JS scripts. The downside is losing some web compatibility in order to achieve fast speeds.
  • Its: Webkit is the kernel used by Safari. The advantage of Webkit is that it has faster web browsing speed, which is not as fast as Presto but better than Gecko and Trident. The disadvantage is that it has low error tolerance for web code, which means it has low compatibility with web code. Will make some of the compilation of non-standard web pages can not be displayed correctly. WebKit is the predecessor of KDE group’s KHTML engine, so WebKit is an open source branch of KHTML.
  • Blink: In a Blog post on The Chromium Blog, Google announced that it would break away from Apple’s open source browser core, Webkit, and develop a Blink rendering engine (or browser core) in Chromium project to be built into Chrome. The Blink engine is a branch of Webkit, just as Webkit is a branch of KHTML. The Blink engine is currently being developed by Google in collaboration with Opera Software, who, as mentioned above, abandoned their Own Presto kernel and joined Google in developing Blink.

4. Kernel used by common browsers

(1) Internet Explorer kernel: Trident kernel, also known as IE kernel;

(2) Chrome browser kernel: collectively referred to as Chromium kernel or Chrome kernel, formerly Webkit kernel, now Blink kernel;

(3) Firefox kernel: Gecko kernel, commonly known as Firefox kernel;

(4) Safari kernel: Webkit kernel;

(5) Opera browser kernel: originally its own Presto kernel, then joined the Google army, from Webkit to Blink kernel;

(6) 360 browser, Cheetah browser kernel: IE + Chrome dual kernel;

(7) Sogou, Pengyou, QQ browser kernel: Trident (compatible mode) + Webkit (high-speed mode);

(8) Baidu browser, window of the world kernel: IE kernel;

(9) 2345 Browser kernel: it seems that it used to be IE kernel, now it is also IE + Chrome dual kernel;

(10) UC Browser kernel: There is a lot of disagreement about this. UC says it is their own U3 kernel, but it seems to be based on Webkit and Trident, and some say it is based on the Firefox kernel.

5. The main components of the browser

  • The user interface includes the address bar, forward/back buttons, bookmarks menu, etc. Every part of the display except for the page you requested in the browser’s main window belongs to the user interface.
  • The browser engine passes instructions between the user interface and the rendering engine.
  • The rendering engine is responsible for displaying the requested content. If the requested content is HTML, it parses the HTML and CSS content and displays the parsed content on the screen.
  • Networks are used for network calls, such as HTTP requests. Its interface is platform independent and provides the underlying implementation for all platforms.
  • The user interface back end is used to draw basic widgets, such as combo boxes and Windows. It exposes a common interface that is platform-independent and uses the operating system’s user interface approach underneath.
  • The JavaScript interpreter. Used to parse and execute JavaScript code.
  • Data store this is the persistence layer. Browsers need to keep various kinds of data, such as cookies, on hard drives. The new HTML specification (HTML5) defines the “Web database,” which is a complete (but lightweight) in-browser database.

It’s worth noting that unlike most browsers, Chrome has one instance of the rendering engine for each TAB. Each TAB is an independent process.

Principles of browser rendering

1. Browser rendering process

Browser rendering mainly has the following steps:

  • First, the received document is parsed and a DOM tree is built according to the document definition. The DOM tree is composed of DOM elements and attribute nodes.
  • Then the CSS is parsed to generate the CSSOM rule tree.
  • Build the render tree from the DOM tree and the CSSOM rule tree. The nodes of the render tree are called render objects. A render object is a rectangle containing properties such as color and size. The render object corresponds to a DOM element, but the correspondence is not one-to-one. There are also DOM elements that correspond to several visible objects, usually elements with a complex structure that cannot be described by a rectangle.
  • When the render objects are created and added to the tree, they have no position or size, so when the browser generates the render tree, it is laid out according to the render tree (also known as reflux). What the browser needs to do at this stage is to figure out the exact location and size of each node in the page. This behavior is often referred to as “automatic rearrangement.”
  • After the layout phase is the draw phase, which traverses the render tree and calls the render objects’ paint methods to display their contents on the screen. The draw uses the UI base component.

The general process is shown in the figure:

Note: This process is done step by step, the render engine will render the content to the screen as early as possible for a better user experience, and will not wait until all the HTML has been parsed before building and laying out the Render tree. It parses part of the content and displays part of the content, while probably downloading the rest of the content over the network.

2. Optimize browser rendering

(1) For JavaScript: JavaScript blocks both HTML and CSS parsing. So we can optimize this by changing the way JavaScript loads:

(1) Try to place the JavaScript file at the end of the body

(2) Try not to write

(3) There are three ways to import resources with

  • Script immediately stop page rendering to load the resource file, when the resources are loaded, immediately execute THE JS code, js code execution is finished, continue to render the page;
  • Async is loaded asynchronously immediately after the download is completed, and executed immediately after loading. Multiple tags with async attribute cannot guarantee the loading order;
  • Defer is loaded asynchronously immediately after the download is complete. After loading, if the DOM tree is not built yet, wait until the DOM tree is parsed. If the DOM tree is ready, execute immediately. Multiple tags with the defer attribute are executed in order.

(2) For CSS: There are three ways to use CSS: using link, @import, and inline styles, where link and @import import external styles. The difference between them:

  • Link: The browser sends a new wait thread (HTTP thread) to load the resource file, while the GUI rendering thread continues to render the code down
  • @import: The GUI rendering thread will temporarily stop rendering, go to the server to load the resource file, and will not continue rendering until the resource file returns (hindering browser rendering)
  • Style: GUI direct rendering

If the external style has not been loaded for a long time, the browser will use the default style for user experience, ensuring the speed of the first rendering. So CSS is usually written in the headr, allowing the browser to send a request to get the CSS style as soon as possible.

So, during development, import external styles using link instead of @import. If you have less CSS, use inline styles if possible, and write them directly in the style tag.

(3) For DOM tree, CSSOM tree: There are several ways to reduce the rendering time:

  • The code level of the HTML file should not be too deep
  • Use semantic tags to avoid special processing that is not standard semantic
  • Reduce the hierarchy of CSSD code because selectors are resolved from left to right

(4) Reduce reflux and redraw:

  • When operating the DOM, try to operate on lower-level DOM nodes
  • Don’t usetableLayout, a small change may make the wholetableTo rearrange
  • Expressions that use CSS
  • Do not frequently manipulate the style of the element. For static pages, you can change the class name, not the style.
  • Use Absolute or fixed to remove elements from the document flow so that changes to them do not affect other elements
  • Instead of manipulating the DOM frequently, you can create a document fragmentdocumentFragment, apply all the DOM operations on it, and finally add it to the document
  • Set the element firstdisplay: noneAnd then display it after the operation is over. Because DOM operations on elements with the display attribute none do not cause reflow and redraw.
  • Multiple read (or write) operations of the DOM are grouped together, rather than read and write operations interspersed with writes. This is thanks to the browser’s render queue mechanism.

Browser for page reflux and redraw, for its own optimization – render queue

The browser puts all the backflow and redraw operations in a queue, and when the queue reaches a certain number of operations or a certain time interval, the browser batches the queue. This will allow multiple backflow, redraw into a backflow redraw.

When multiple reads (or writes) are grouped together, they wait until all the reads are queued, and instead of triggering multiple backflows, they trigger only one.

3. How to deal with JS files encountered during rendering?

The loading, parsing, and execution of JavaScript blocks the parsing of the document. That is, if the HTML parser encounters JavaScript while building the DOM, it will pause the parsing of the document and hand over control to the JavaScript engine. Once the JavaScript engine is finished, the browser picks up where it left off and continues parsing the document. That is, the faster you want to render the first screen, the less you should load the JS file on the first screen, which is why it is recommended to place the script tag at the bottom of the body tag. At the moment, it doesn’t mean that the script tag has to be placed at the bottom, as you can add either defer or async attributes to the script tag.

4. What is pre-parsing of documents?

Both Webkit and Firefox make this optimization so that when the JavaScript script is executed, another thread parses the remaining document and loads the resources that later need to be loaded over the network. This way, the resources can be loaded in parallel, making the overall speed faster. Note that pre-parsing doesn’t change the DOM tree; it leaves that up to the main parsing process and only parses references to external resources, such as external scripts, stylesheets, and images.

5. How does CSS block document parsing?

In theory, since the stylesheet does not change the DOM tree, there is no need to stop parsing documents and wait for them. One problem, however, is that an executing JavaScript script may request style information during the parsing of the document. If the style has not yet been loaded and parsed, the script will get the wrong value, which obviously can cause a lot of problems. So if we want to run the script while the browser has not yet completed the CSSOM download and build, the browser will delay JavaScript script execution and document parsing until it has completed the CSSOM download and build. That is, in this case, the browser downloads and builds the CSSOM, then executes the JavaScript, and finally continues parsing the document.

6. How to optimize critical render paths?

To do the first render as quickly as possible, we need to minimize the following three variables:

(1) The number of key resources.

(2) Critical path length.

(3) The number of key bytes.

The key resource is the resource that may prevent the first rendering of the page. The fewer these resources, the less work the browser needs and the less CPU and other resources it consumes. Similarly, the critical path length is influenced by a dependency graph between all critical resources and their byte size: some resources can only be downloaded after the previous resource has been processed, and the larger the resource, the more round trips the download takes. Finally, the fewer key bytes the browser needs to download, the faster it can process the content and bring it to the screen. To reduce the number of bytes, we can reduce the number of resources (delete them or make them non-critical), and also compress and optimize resources to ensure that the transfer size is minimized.

The general steps to optimize the critical render path are as follows:

(1) Analyze and describe the critical paths: number of resources, number of bytes, and length.

(2) Minimize the number of critical resources: delete them, delay their download, mark them as asynchronous, etc.

(3) Optimize the number of key bytes to shorten the download time (round trip).

(4) Optimize the load order of the remaining critical resources: you need to download all critical assets as early as possible to shorten the critical path length

7. What conditions block rendering?

The first rendering premise is to generate the render tree, so HTML and CSS will definitely block the rendering. If you want to render faster, you should reduce the size of the file to render in the first place, flatline it, and optimize the selectors. Then, when the browser parses to the script tag, it pauses building the DOM, and when it’s done, it picks up where it left off. That is, the faster you want to render the first screen, the less you should load the JS file on the first screen, which is why it is recommended to put the script tag at the bottom of the body tag.

At the moment, it doesn’t mean that the script tag has to be placed at the bottom, as you can add either defer or async attributes to the script tag. When the script tag is added as defer, it means that the JS file will be downloaded in parallel but will be executed sequentially after the HTML is parsed, so you can put the script tag anywhere in this case. For JS files that do not have any dependencies, you can add the async property to indicate that the JS file download and parsing will not block rendering.

6. Browser local storage

1. The local storage mode and application scenario of the browser

(1) the Cookie

Cookie is the earliest proposed local storage method. Before that, the server was unable to determine whether the two requests in the network were initiated by the same user. To solve this problem, Cookie appeared. A Cookie is only 4KB in size and is a plain text file that is carried with each HTTP request.

Cookie features:

  • Once the Cookie is created, the name cannot be changed
  • Cookies cannot cross domain names, that is to say, cookies under domain names A and B cannot be shared, which is also determined by the privacy security of cookies, so as to prevent illegal access to other websites’ cookies
  • The number of cookies under each domain name cannot exceed 20, and the size of each Cookie cannot exceed 4KB
  • There is a security problem. If the Cookie is intercepted, then all the information of the session can be obtained, even if the encryption is useless. You don’t need to know the meaning of the Cookie
  • Cookies are sent whenever a new page is requested

If you need to share cookies between domains across domains, there are two methods:

  1. Use the Nginx reverse proxy
  2. After logging in to one site, write cookies to other sites. The Session on the server is stored on a node, and the Cookie stores the Session ID

Cookie usage scenarios:

  • The most common usage scenario is the combination of Cookie and session. We store the sessionId in the Cookie and carry the sessionId with each request so that the server knows who made the request and can respond accordingly.
  • Can be used to count the number of clicks on the page

(2) the LocalStorage

LocalStorage is the new introduction of HTML5 features, because sometimes we store a large amount of information, cookies can not meet our needs, this time LocalStorage will come in handy.

Advantages of LocalStorage:

  • In terms of size, the size of LocalStorage is generally 5MB, which can store more information
  • LocalStorage is persistent storage, will not disappear with the page closed, unless the initiative to clean up, otherwise will exist permanently
  • Stored locally only, unlike cookies, which are carried with each HTTP request

Disadvantages of LocalStorage:

  • Browsers later than Internet Explorer 8 do not support it
  • If the browser is set to private mode, we will not be able to read LocalStorage
  • The LocalStorage is restricted by the same-origin policy. If the port, protocol, or host address are different, the LocalStorage cannot be accessed

LocalStorage API:

// Save data to localStorage
localStorage.setItem('key'.'value');

// Obtain data from localStorage
let data = localStorage.getItem('key');

// Delete the saved data from localStorage
localStorage.removeItem('key');

// Delete all saved data from localStorage
localStorage.clear();

// Get the Key of an index
localStorage.key(index)
Copy the code

Application scenarios of LocalStorage:

  • Some websites have the function of skin, this time you can skin information stored in the local LocalStorage, when the need to skin, direct operation of LocalStorage can be
  • The user browsing information in the website will also be stored in the LocalStorage, and the website of some of the personal information that does not often change can also be stored in the local LocalStorage

(3) the SessionStorage

SessionStorage and LocalStorage are proposed in HTML5 storage solutions, SessionStorage is mainly used to temporarily save the same window (or label) data, refresh the page will not be deleted, close the window or label after the data will be deleted.

SessionStorage and LocalStorage:

  • SessionStorage and LocalStorage both store data locally.
  • SessionStorage also has the same origin policy. However, SessionStorage has a stricter restriction. SessionStorage can be shared only in the same browser and the same window.
  • LocalStorage and SessionStorage cannot be crawled by crawlers.

SessionStorage common API:

// Save data to sessionStorage
sessionStorage.setItem('key'.'value');

// Obtain data from sessionStorage
let data = sessionStorage.getItem('key');

// Delete the saved data from sessionStorage
sessionStorage.removeItem('key');

// Delete all saved data from sessionStorage
sessionStorage.clear();

// Get the Key of an index
sessionStorage.key(index)
Copy the code

Usage scenarios of SessionStorage

  • Because SessionStorage is time-sensitive, it can be used to store some website’s visitor login information, as well as temporary browsing record information. When the site is closed, the information is removed.

2. What are the fields of a Cookie and what are their functions

A Cookie consists of the following fields:

  • Name: Indicates the Name of the cookie
  • Value: The Value of the cookie. For authentication cookies, the Value includes the access token provided by the Web server;
  • Size: Indicates the Size of the cookie
  • Path: The path to the page where this cookie can be accessed. For example, domain is abc.com and path is/test, then only/testThe cookie can be read by pages under the path.
  • Secure: Specifies whether to send cookies using the HTTPS security protocol. The HTTPS security protocol protects cookies from being stolen and tampered with during transmission between the browser and the Web server. This method can also be used for Web site authentication, where the browser checks the validity of the Web site’s SSL certificate during the HTTPS connection establishment phase. However, for compatibility reasons (for example, some sites use self-signed certificates), when the SSL certificate is detected to be invalid, the browser does not immediately terminate the user’s connection request. Instead, the browser displays security risk information, and the user can still choose to continue to access the site.
  • Domain: Domain that can access the cookie. The cookie mechanism does not follow a strict same-origin policy and allows a subdomain to set or obtain the cookie of its parent Domain. The above features of cookies are useful when implementing single sign-on schemes, but they also increase the risk of Cookie attacks, such as session setting attacks. Therefore, you are not allowed to set generic top-level domains (TLDS) such as.org and.com in the Domain attribute of the browser, and secondary Domain names registered under the country or region TLDS to reduce the attack scope.
  • HTTP: This field containsHTTPOnlyProperty that sets whether the cookie can be accessed from a script. The default value is null, meaning that the cookie can be accessed from a script. It is not possible to set an httpOnly type cookie on the client via JS code. This type of cookie can only be set on the server. This property is used to prevent client scripts from passingdocument.cookieProperties to help protect cookies from being stolen or tampered with by cross-site scripting attacks. However, the application of HTTPOnly still has limitations. Some browsers can prevent client scripts from reading cookies, but allow write operations. In addition, most browsers still allow set-cookie headers in HTTP responses to be read through XMLHTTP objects.
  • Expires/ max-size: Indicates the timeout period of the cookie. If the value is set to a time, the cookie becomes invalid when that time is reached. If not set, the default value is Session, which means that the cookie will be invalidated along with the Session. This cookie is invalid when the browser is closed (not the browser TAB, but the entire browser).

Summary: The server can use the response header of set-cookie to configure Cookie information. A cookie contains five property values: Expires, Domain, path, Secure, and HttpOnly. Expires specifies the time when a cookie expires, domain is a domain name, and path is a path. Together, domain and path limit which urls a cookie can be accessed. Secure specifies that the cookie can only be transmitted when it is secured. HttpOnly specifies that the cookie can only be accessed by the server, not by js scripts.

3. Differences between Cookie, LocalStorage, and SessionStorage

The commonly used storage technologies in the browser are cookie, localStorage, and sessionStorage.

  • Cookie: It is actually a way for the server to record the user’s state. It is set by the server, stored in the client, and then sent to the server every time the same origin request is initiated. A cookie can store up to 4 KB of data, its lifetime is specified by the Expires attribute, and the cookie can only be shared by pages of the same origin.
  • SessionStorage: A browser-local storage method provided by HTML5. It borrows the concept of a server-side session, which represents the data saved in a session. It is typically capable of storing 5M or more data, it fails after the current window is closed, and sessionStorage can only be shared by the same page in the same window.
  • LocalStorage: html5 provides a browser localStorage method, it is generally able to store 5M or more data. Unlike sessionStorage, it does not fail unless you manually delete it, and localStorage can only be accessed and shared by the same page.

The above methods are for storing small amounts of data, but when you need to store large amounts of data locally, you can use the browser’s indexDB, which is a local database storage mechanism provided by the browser. Instead of being a relational database, it stores data internally in the form of an object warehouse, which is closer to a NoSQL database.

4. What are the front-end storage methods?

  • Cookies: the main way of local storage before THE HTML5 standard. Its advantages are good compatibility and convenient to have cookies in the request header. Its disadvantages are that the size is only 4K, and adding cookies to the automatic request header wastes traffic.
  • LocalStorage: HTML5 added to the key-value (key-value) as the standard way, the advantage is easy to operate, permanent storage (unless manually deleted), the size of 5M, compatible with IE8+;
  • SessionStorage: Similar to localStorage. The difference is that sessionStorage is cleaned up after the page is closed. Different from cookie and localStorage, sessionStorage cannot be shared in all the same window.
  • The Web SQL: In 2010, W3C abandoned the local database data storage scheme, but the mainstream browser (except Firefox) have relevant implementation, Web SQL is similar to SQLite, is a relational database in the real sense, using SQL to operate, when we use JavaScript to convert, more cumbersome;
  • IndexedDB is a database storage solution officially incorporated into the HTML5 standard. It is a NoSQL database that is stored in key-value pairs and can be read quickly. It is ideal for Web scenarios and can be easily operated in JavaScript.

What are the features of IndexedDB?

IndexedDB has the following features:

  • Key-value pair storage: The IndexedDB uses the Object Store to store data. All types of data can be stored directly, including JavaScript objects. In the object warehouse, data is stored in the form of “key and value pairs”. Each data record has a corresponding primary key. The primary key is unique and cannot be repeated, otherwise an error will be thrown.
  • Asynchronous: IndexedDB operations do not lock the browser and users can still perform other operations, in contrast to LocalStorage, where operations are synchronous. The asynchronous design is designed to prevent large amounts of data being read and written, slowing down the performance of the web page.
  • Support for transactions: IndexedDB supports transactions, which means that if one of the steps fails, the entire transaction is cancelled and the database is rolled back to the state before the transaction occurred. There is no overwriting only part of the data.
  • Same-origin restriction: IndexedDB is subject to same-origin restriction, with each database corresponding to the domain name for which it was created. A web page can only access databases within its own domain name, but cannot access databases across domains.
  • Large storage space: the storage space of IndexedDB is much larger than that of LocalStorage. Generally speaking, the storage space of IndexedDB is no less than 250MB, and even there is no upper limit.
  • Support for binary storage: IndexedDB can store not only strings but also binary data (ArrayBuffer objects and Blob objects).

7. Browser same-origin policy

1. What is the same Origin policy

The cross-domain problem is caused by the browser’s same origin policy.

Same-origin policies restrict how documents or scripts loaded from one source can interact with resources from another source. This is an important security mechanism for browsers to isolate potentially malicious files. Same-origin indicates that the protocol, port number, and domain name must be the same.

The table below gives the with URL store.company.com/dir/page.ht… For example:

URL Whether the cross-domain why
Store.company.com/dir/page.ht… homologous Exactly the same
Store.company.com/dir/inner/a… homologous Only the path is different
store.company.com/secure.html Cross domain Agreement is different
Store.company.com: 81 / dir/etc. HTM… Cross domain Different ports (http://default port is 80)
News.company.com/dir/other.h… Cross domain The host different

Same-origin policy: Protocol, domain, and port must be the same.

The same origin policy has three main limitations:

  • Js scripts in the current domain cannot access cookies, localStorage, and indexDB in other domains.
  • The JS scripts in the current domain cannot operate the DOM in other domains.
  • Ajax cannot send cross-domain requests in the current domain.

Main aim of the same-origin policy is to ensure that the user information security, it’s just a limit of js script, is not the limitation on the browser, for general img or script script requests will not cross-domain limitation, that is because these operations are not through the response result to possible security problems.

2. How to solve the crossing problem

(1) the CORS

The following is the definition of CORS by MDN:

Cross-domain resource sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers that Web applications running on an Origin (domain) are allowed to access specified resources from different source servers. When a resource requests a resource from a different domain, protocol, or port than the server where the resource itself resides, the resource initiates a cross-domain HTTP request.

CORS requires both browser and server support. The entire CORS process is completed by the browser without user participation. Therefore, the key to realize CORS is the server. As long as the server implements CORS requests, it can communicate across sources.

Browsers divide CORS into simple and non-simple requests:

Simple requests do not trigger CORS precheck requests. A request is considered simple if it meets two conditions:

1) Request method is one of the following three methods:

  • HEAD
  • GET
  • POST

2) HTTP header information should not exceed the following fields:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-type: Only three values: Application/X-www-form-urlencoded, Multipart /form-data, text/plain

If the above conditions are not met, it is a non-simple request.

(1) Simple request process:

For simple requests, the browser makes a CORS request directly. It adds an Orign field to the request header. This field specifies which source (protocol + port + domain name) the request came from, and the server uses this value to decide whether to approve the request. If the domain name specified by Orign is within the scope of the license, the server will return the response with the following headers:

Access-Control-Allow-Origin: http://api.bob.com // and Orign all the time
Access-Control-Allow-Credentials: true   // Indicates whether cookies are allowed to be sent
Access-Control-Expose-Headers: FooBar   // Specifies to return the values of the other fields
Content-Type: text/html; charset=utf-8   // Represents the document type
Copy the code

If the domain name specified by Orign is not licensed, the server will return a normal HTTP response, and the browser will know that there is no access-control-allow-Origin header. This error cannot be identified by the status code, because the returned status code might be 200.

In a simple request, within the server, you need to set at least the field access-control-allow-Origin

(2) Non-simple request process

Non-simple requests are requests that have special requirements for the server, such as the request method DELETE or PUT. A CORS request that is not a simple request is preceded by an HTTP query request, called a precheck request.

The browser will ask the server whether the current page is within the scope of the server to access, and which HTTP request mode and header field can be used. Only when the response is positive, will the formal HTTP request be made, otherwise, an error will be reported.

The precheck request uses the request method OPTIONS, which indicates that the request is to be asked. The key field in his header is Orign, which indicates the source from which the request came. In addition, the header information includes two fields:

  • Access-control-request-method: This field is required to list which HTTP methods are used for browser CORS requests.
  • Access-control-request-headers: This field is a comma-separated string that specifies the additional header field that will be sent for browser CORS requests.

After receiving the precheck request from the browser, the server will make a judgment based on the three fields of the header information. If the returned header contains the access-control-allow-Origin field, the cross-domain request is allowed. If the returned header does not contain the access-control-allow-Origin field, it does not agree to the precheck request, and an error will be reported.

The server responds with the following fields for CORS:

Access-Control-Allow-Origin: http://api.bob.com // Allow cross-domain source addresses
Access-Control-Allow-Methods: GET, POST, PUT // All cross-domain request methods supported by the server
Access-Control-Allow-Headers: X-Custom-Header  // All header fields supported by the server
Access-Control-Allow-Credentials: true   // Indicates whether cookies are allowed to be sent
Access-Control-Max-Age: 1728000  // Specifies the validity period of the precheck request, in seconds
Copy the code

As long as the server passes the precheck request, every CORS request will come with an Origin header field. The server’s response also has an access-control-allow-Origin header field.

In a non-simple request, at least the following fields need to be set:

'Access-Control-Allow-Origin'  
'Access-Control-Allow-Methods'
'Access-Control-Allow-Headers'
Copy the code
Reduce the number of OPTIONS requests:

Too many OPTIONS requests will impair page loading performance and reduce user experience. To minimize the number of OPTIONS requests, add access-control-max-age: number to the return header of the request. It indicates how long, in seconds, the return result of the precheck request can be cached. This field is only valid for the same URL cache Settings, so the cache time is set, within which the request is sent again without prechecking the request.

Cookie related issues in CORS:

In a CORS request, if you want to pass a Cookie, you must meet the following three conditions:

  • Set in the requestwithCredentials

By default, browsers do not carry cookies on cross-domain requests. But we can pass cookies by setting withCredentials.

// How to set native XML
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
// Axios Settings
axios.defaults.withCredentials = true;
Copy the code
  • Set the access-control-allow-credentials to true
  • Access-control-allow-origin is set to non*

(2) the json

The

<script>
    var script = document.createElement('script');
    script.type = 'text/javascript';
    // Pass a callback function name to the back end to make it easier for the back end to execute the callback function defined in the front end when it returns
    script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
    document.head.appendChild(script);
    // Callback to the execution function
    function handleCallback(res) {
        alert(JSON.stringify(res));
    }
 </script>
Copy the code

The server returns the following (when returned, the global function is executed) :

handleCallback({"success": true."user": "admin"})
Copy the code

2) Vue Axios implementation:

this.$http = axios;
this.$http.jsonp('http://www.domain2.com:8080/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) = > {
    console.log(res); 
})
Copy the code

Backend Node.js code:

var querystring = require('querystring');
var http = require('http');
var server = http.createServer();
server.on('request'.function(req, res) {
    var params = querystring.parse(req.url.split('? ') [1]);
    var fn = params.callback;
    // Jsonp returns Settings
    res.writeHead(200, { 'Content-Type': 'text/javascript' });
    res.write(fn + '(' + JSON.stringify(params) + ') ');
    res.end();
});
server.listen('8080');
console.log('Server is running at port 8080... ');
Copy the code

Disadvantages of JSONP:

  • Limited, only the GET method is supported
  • It is not secure and may be subject to XSS attacks

(3) postMessage cross-domain

PostMessage is an API in HTML5 XMLHttpRequest Level 2 and is one of the few window properties that can be operated across domains. It can be used to solve the following problems:

  • Data transfer between the page and the new window it opens
  • Messaging between multiple Windows
  • Page with nested IFrame message delivery
  • Cross-domain data transfer for the three scenarios above

The postMessage(data,origin) method takes two arguments:

  • Data: The HTML5 specification supports any basic type or replicable object, but some browsers only support strings, so it’s best to serialize with json.stringify () when passing arguments.
  • Origin: protocol + host + port number. It can also be set to “*”, indicating that it can be passed to any window, or “/” if you want to specify the same origin as the current window.

1) a) HTML (domain1.com/a.html)

<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>       
    var iframe = document.getElementById('iframe');
    iframe.onload = function() {
        var data = {
            name: 'aym'
        };
        // Send cross-domain data to Domain2
        iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com');
    };
    // Accept the data returned by Domain2
    window.addEventListener('message'.function(e) {
        alert('data from domain2 ---> ' + e.data);
    }, false);
</script>
Copy the code

2)b.html:(domain2.com/b.html)

<script>
    // Receive data from Domain1
    window.addEventListener('message'.function(e) {
        alert('data from domain1 ---> ' + e.data);
        var data = JSON.parse(e.data);
        if (data) {
            data.number = 16;
            // After processing, send back to Domain1
            window.parent.postMessage(JSON.stringify(data), 'http://www.domain1.com'); }},false);
</script>
Copy the code

(4) NGINx agent cross-domain

Nginx proxy cross-domain, essence and CORS cross-domain principle, through the configuration file to set the request response header access-control-allow-origin… And other fields.

1) nginx configuration solution iconfont cross-domain browser cross-domain access js, CSS, and img conventional static resources are the same-origin policy permission, but iconfont font file (eot | otf | the vera.ttf | woff | SVG) exception, at this time in nginx server to add the following configuration static resources.

location / {
  add_header Access-Control-Allow-Origin *;
}
Copy the code

2) Nginx reverse proxy interface cross-domain cross-domain problem: The same-origin policy is only a security policy for browsers. The server side only uses THE HTTP protocol to call the HTTP interface, and does not need the same origin policy, so there is no cross-domain problem. Implementation idea: Through Nginx, configure a proxy server with the same domain name as domain1 and different ports) to act as a jumper, access the interface of domain2 through reverse proxy, and modify the domain information in cookies in the way to facilitate the writing of cookies in the current domain and achieve cross-domain access.

Nginx configuration:

# Proxy server server {listen81;
    server_name  www.domain1.com;
    location / {
        proxy_pass   http://www.domain2.com:8080; # Reverse proxyproxy_cookie_domain www.domain2.com www.domain1.com; # Modify cookie index. HTML index. HTM; Add_header access-control-allow-origin HTTP: add_header access-control-allow-origin HTTP: add_header access-control-allow-origin HTTP: add_header access-control-allow-origin HTTP: add_header access-control-allow-origin//www.domain1.com; * is used when the current end is cross-domain and does not contain cookies
        add_header Access-Control-Allow-Credentials true; }}Copy the code

(5) NodeJS middleware proxy is cross-domain

Node middleware implements cross-domain proxy. The principle of node middleware is roughly the same as that of Nginx. In both cases, a proxy server is set up to forward data.

1) Use Node + Express + HTTP-proxy-middleware to build a proxy server for cross-domain non-VUE framework.

  • Front-end code:
var xhr = new XMLHttpRequest();
// Front switch: whether the browser reads and writes cookies
xhr.withCredentials = true;
// Access the http-proxy-Middleware proxy server
xhr.open('get'.'http://www.domain1.com:3000/login?user=admin'.true);
xhr.send();
Copy the code
  • Middleware server code:
var express = require('express');
var proxy = require('http-proxy-middleware');
var app = express();
app.use('/', proxy({
    // Proxy cross-domain target interface
    target: 'http://www.domain2.com:8080'.changeOrigin: true.// Modify the response header to cross domains and allow cookies
    onProxyRes: function(proxyRes, req, res) {
        res.header('Access-Control-Allow-Origin'.'http://www.domain1.com');
        res.header('Access-Control-Allow-Credentials'.'true');
    },
    // Modify the cookie domain name in the response information
    cookieDomainRewrite: 'www.domain1.com'  // The value can be false, indicating no modification
}));
app.listen(3000);
console.log('Proxy server is listen at port 3000... ');
Copy the code

2) Cross-domain vUE framework

Node + vue + webpack + webpack-dev-server project, cross-domain request interface, directly modify webpack.config.js configuration. In the development environment, vue rendering service and interface proxy service are the same Webpack-dev-server, so there is no cross-domain between the page and the proxy interface.

Webpack.config.js part configuration:

module.exports = {
    entry: {},
    module: {},...devServer: {
        historyApiFallback: true.proxy: [{
            context: '/login'.target: 'http://www.domain2.com:8080'.// Proxy cross-domain target interface
            changeOrigin: true.secure: false.// This is used when the proxy for some HTTPS service reports an error
            cookieDomainRewrite: 'www.domain1.com'  // The value can be false, indicating no modification}].noInfo: true}}Copy the code

(6) Document.domain + iframe cross-domain

This solution applies only to cross-domain scenarios where the primary domain is the same but the subdomains are different. Implementation principle: two pages through JS mandatory set document.domain as the basis of the primary domain, the implementation of the same domain. 1) parent window :(domain.com/a.html)

<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
    document.domain = 'domain.com';
    var user = 'admin';
</script>
Copy the code

1) child window :(child.domain.com/a.html)

<script>
    document.domain = 'domain.com';
    // Get the variables in the parent window
    console.log('get js data from parent ---> ' + window.parent.user);
</script>
Copy the code

(7) Location. hash + iframe cross-domain

Implementation principle: A wants to communicate with B across domains through the middle page C. Three pages. Different domains pass values using the location.hash of iframe, and the same domains directly communicate with each other by JS access.

Specific implementation: A domain: a.HTML -> B domain: B.html -> A domain: C.tml, A and B different domain can only hash value one-way communication, B and C also different domain can only one-way communication, but C and A domain, so C can access all objects of A page through parent. Parent.

1) a) HTML (domain1.com/a.html)

<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>
    var iframe = document.getElementById('iframe');
    // Pass the hash value to B.html
    setTimeout(function() {
        iframe.src = iframe.src + '#user=admin';
    }, 1000);
    
    // Open callback methods to the same domain AS C.html
    function onCallback(res) {
        alert('data from c.html ---> ' + res);
    }
</script>
Copy the code

2)b.html:(.domain2.com/b.html)

<iframe id="iframe" src="http://www.domain1.com/c.html" style="display:none;" ></iframe> <script> var iframe = document.getElementById('iframe'); Window.onhashchange = function () {iframe.src = iframe.src + location.hash; }; </script>Copy the code

3)c.html:(www.domain1.com/c.html)

<script>
    // Listen for hash values from B.html
    window.onhashchange = function () {
        // The result is returned by the js callback that manipulates the same field as a.html
        window.parent.parent.onCallback('hello: ' + location.hash.replace('#user='.' '));
    };
</script>
Copy the code

(8) window.name + iframe cross-domain

The unique feature of the window.name property is that the name value will persist across different pages (or even different domain names), and very long name values (2MB) can be supported.

1) a) HTML (domain1.com/a.html)

var proxy = function(url, callback) {
    var state = 0;
    var iframe = document.createElement('iframe');
    // Load the cross-domain page
    iframe.src = url;
    // The onLoad event is triggered twice. The first time loads the cross-domain page and stores the data in window.name
    iframe.onload = function() {
        if (state === 1) {
            // After the second onload(the same domain proxy page) succeeds, read the data in the same domain window.name
            callback(iframe.contentWindow.name);
            destoryFrame();
        } else if (state === 0) {
            // After the first onload(cross-domain page) succeeds, switch to the co-domain agent page
            iframe.contentWindow.location = 'http://www.domain1.com/proxy.html';
            state = 1; }};document.body.appendChild(iframe);
    // Destroy the iframe after obtaining the data, freeing the memory; This also ensures security (not being accessed by other domains frame JS)
    function destoryFrame() {
        iframe.contentWindow.document.write(' ');
        iframe.contentWindow.close();
        document.body.removeChild(iframe); }};// Request cross-domain B page data
proxy('http://www.domain2.com/b.html'.function(data){
    alert(data);
});
Copy the code

2) proxy.html (domain1.com/proxy.html)

Intermediate proxy page, same field as A.HTML, content is empty. 3) B.tml (domain2.com/b.html)

<script>    
    window.name = 'This is domain2 data! ';
</script>
Copy the code

The SRC attribute of the iframe is used to transfer cross-domain data from the outer domain to the local domain. The window. This neatly circumvents the browser’s cross-domain access restrictions, but at the same time it is a secure operation.

(9) WebSocket protocol cross-domain

WebSocket Protocol is a new HTML5 protocol. It realizes full-duplex communication between browser and server and allows cross-domain communication. It is a good implementation of Server push technology.

The native WebSocket API is not easy to use, so we use socket. IO, which encapsulates the WebSocket interface nicely, providing a simpler, more flexible interface, and downward compatibility for browsers that don’t support WebSocket.

1) Front-end code:

<div>user input: <input type="text"></div>
<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script>
<script>
var socket = io('http://www.domain2.com:8080');
// The connection was processed successfully
socket.on('connect'.function() {
    // Listen for server messages
    socket.on('message'.function(msg) {
        console.log('data from server: ---> ' + msg); 
    });
    // The listener server is closed
    socket.on('disconnect'.function() { 
        console.log('Server socket has closed.'); 
    });
});
document.getElementsByTagName('input') [0].onblur = function() {
    socket.send(this.value);
};
</script>
Copy the code

2) Nodejs socket background:

var http = require('http');
var socket = require('socket.io');
// Start the HTTP service
var server = http.createServer(function(req, res) {
    res.writeHead(200, {
        'Content-type': 'text/html'
    });
    res.end();
});
server.listen('8080');
console.log('Server is running at port 8080... ');
// Listen for socket connections
socket.listen(server).on('connection'.function(client) {
    // Receive the message
    client.on('message'.function(msg) {
        client.send('hello:' + msg);
        console.log('data from client: ---> ' + msg);
    });
    // Disconnect processing
    client.on('disconnect'.function() {
        console.log('Client socket has closed.'); 
    });
});
Copy the code

3. Differences between the forward proxy and reverse proxy

  • Forward proxy:

The client wants to get data from a server, but for a variety of reasons can’t get it directly. So the client sets up a proxy server and specifies the target server, and then the proxy server forwards the request to the target server and sends the obtained content to the client. This essentially hides the real client from the real server. Implementing the forward proxy requires modifying the client, such as modifying the browser configuration.

  • Reverse proxy:

In order to divide workload into less than one server to improve website performance (load balancing) and other purposes, when receiving a request, the server will first determine which server the request should be forwarded to according to the forwarding rules, and then forward the request to the corresponding real server. This essentially hides the real server from the client. After the reverse proxy is used, you need to change the DNS to resolve the domain name to the proxy server IP address. In this case, the browser cannot detect the existence of the real server. Therefore, you do not need to change the configuration.

The difference between the two is shown in the diagram:The structure of the forward proxy is the same as that of the reverse proxy, both of which are client-proxy-server. The main difference between them lies in which side sets the proxy in the middle. In the forward proxy, proxy is set by the client to hide the client. In reverse proxy, proxy is set by the server to hide the server.

4. Nginx concept and how it works

Nginx is a lightweight Web server that can also be used for reverse proxy, load balancing, AND HTTP caching. Nginx is an HTTP server designed for performance, using an asynchronous event-driven approach to handling requests.

Traditional Web servers such as Apache are based on process-based model, while Nginx is based on event-driven model. It is this major difference that gives Nginx its performance advantage.

At the top of the Nginx architecture is a master process, which is used to generate other worker processes, much like Apache. But the Nginx worker Process can handle a large number of HTTP requests simultaneously, whereas each Apache process can handle only one.

Browser event mechanism

1. What is the event? Event model?

Events are interactive actions that occur when a user operates a web page, such as click/move. In addition to user-triggered actions, events can also be document loading, window scrolling, and resizing. The event is encapsulated as an Event object, which contains all the information related to the event (the event properties) and the actions that can be performed on the event (the event methods).

An event is an interactive action that occurs when a user operates a web page or some operations of the web page itself. Modern browsers have three event models:

  • The dom0-level event model, which does not propagate, does not have the concept of event flow, but some browsers now support the bubbly approach, which can define the listener directly in the web page, or specify the listener through the JS property. All browsers are compatible with this approach. Register event names directly on the DOM object, as DOM0 is written.
  • IE event model, in this event model, an event has two processes, event processing phase and event bubble phase. The event processing phase first executes the listener event bound to the target element. Then there is the event bubbling phase, which refers to the event bubbling from the target element to the Document, checking whether the passing node is bound to the event listener function, and executing if so. This model adds listening functions through attachEvent, and you can add multiple listening functions that are executed in sequence.
  • DOM2 level event model, in this event model, an event has three processes, the first process is the event capture phase. Capture refers to the event propagating from the Document all the way down to the target element, checking in turn whether the passing node is bound to the event listener function, and executing if so. The latter two phases are the same as the two phases of the IE event model. In this event model, the function bound to the event is addEventListener, where the third parameter specifies whether the event is executed during the capture phase.

2. How do I stop events from bubbling

  • Event.stoppropagation ()
  • CancelBubble = true;

3. Understanding of event delegation

(1) The concept of event delegate

Event delegation essentially takes advantage of the browser event bubbling mechanism. Because the event is transmitted to the parent node during the bubble process, the parent node can obtain the target node through the event object, so the listening function of the child node can be defined on the parent node, and the listening function of the parent node can handle the events of multiple child elements in a unified manner, which is called event delegate (event proxy).

Using event delegates reduces memory consumption by eliminating the need to bind a listener event to each child element. For example, if you add a new child node, you don’t need to add a listener event to it. The listener function in the parent element will handle the event binding.

(2) Characteristics of event delegation

  • Reduce memory consumption

If you have a list with a large number of list items, you need to respond to an event when you click on the list item:

<ul id="list">
  <li>item 1</li>
  <li>item 2</li>
  <li>item 3</li>.<li>item n</li>
</ul>
Copy the code

If you bind a function to each of the list items one by one, the memory consumption is very high and the efficiency is very high. Therefore, it is better to bind the click event to its parent layer, namely ul, and then match the target element when executing the event, so the event delegate can reduce a lot of memory consumption and save efficiency.

  • Dynamic binding event

In the above example, each list item is bound to an event. In many cases, the list item elements need to be added or removed dynamically through AJAX or user operations. Each time you change, you need to re-bind the new element to an event and unbind the element to be deleted. If there is no such trouble, use the event delegation for events is binding in the parent layer, and the addition and subtraction of the target element is no relationship, perform to the target element is in response to real event functions in the process to match, so use in the dynamic binding events can be reduced under the condition of a lot of repetitive work.

// to delegate the event proxy of the #list element to its parent element (#list) :
// Bind the event to the parent element
document.getElementById('list').addEventListener('click'.function (e) {
  // Compatibility processing
  var event = e || window.event;
  var target = event.target || event.srcElement;
  // Determine whether the target element is matched
  if (target.nodeName.toLocaleLowerCase === 'li') {
    console.log('the content is: ', target.innerHTML); }});Copy the code

In this code, the target element is the element that is clicked below the #list element, and the target attributes (such as nodeName, id, etc.) can be more accurately matched to a certain type of #list li element.

(3) Limitations

Of course, event delegation has its limits. Events such as Focus, blur and so on do not have event bubble mechanism, so cannot implement event delegate; Events such as mousemove and mouseout, which have event bubbles but only constantly calculate the location through location, are expensive and therefore not suitable for event delegates.

Of course, event delegate is not only good, it also has disadvantages, the event delegate can affect the performance of the page, the main factors are:

  • Element, the number of times event delegates are bound
  • Click between the bottom element and the binding event elementDOMLayer;

Where event delegates must be used, do the following:

  • Use event delegates only where necessary, such as:ajaxLocal refresh area
  • Minimize the level of binding, not inbodyElement
  • Reduce the number of bindings and, if possible, combine the bindings of multiple events into a single event delegate, which will be distributed by the callback of the event delegate.

4. Use scenarios of event delegate

Scenario: Add the click event to all a tags on the page as follows:

document.addEventListener("click".function(e) {
	if (e.target.nodeName == "A")
		console.log("a");
}, false);
Copy the code

But these A tags may contain elements like span, img, etc. If you click on an element in one of these A tags, the click event will not be triggered because the event is bound to the a tag element. E.t. get refers to the element (span, img, and so on) that triggers the click event.

In this case, you can use the event delegate, which binds the event to the inner element of the A tag. When clicked, the event is looked up until the a tag is found.

document.addEventListener("click".function(e) {
	var node = e.target;
	while(node.parentNode.nodeName ! ="BODY") {
		if (node.nodeName == "A") {
			console.log("a");
			break; } node = node.parentNode; }},false);
Copy the code

5. The difference between synchronous and asynchronous

  • Synchronization means that when a process is executing a request, if the request takes a while to return, the process will wait until the message is returned and then continue to execute.
  • Asynchronism is when a process is executing a request, and if the request takes a while to return, the process will continue executing without blocking the message, and then the system will notify the process to process when the message returns.

6. Understanding the event loop

Because JS is run in a single thread, the code is executed in order by pushing the execution context of different functions onto the execution stack. If an asynchronous event is encountered while executing synchronous code, the JS engine does not wait for its return. Instead, it suspends the event and continues to execute other tasks in the execution stack. After the asynchronous event is executed, the callback corresponding to the asynchronous event is added to a task queue for execution. Task queue can be divided into macro task queue and micro task queue. When the event in the current execution stack is completed, js engine will first judge whether there are tasks in the micro task queue that can be executed, if there are, the event at the head of the micro task queue will be pushed into the stack for execution. Tasks in the macro task queue can be executed after all tasks in the microtask queue have been executed.

The sequence of Event loops is as follows:

  • The synchronization code is executed first, which is a macro task
  • When all synchronous code has been executed, the execution stack is empty and queries whether any asynchronous code needs to be executed
  • Perform all microtasks
  • When all microtasks are performed, the page is rendered if necessary
  • The next Event Loop is started, executing the asynchronous code in the macro task

7. What are macro tasks and microtasks

  • Microtasks include: callbacks for promises, process.nextTick in Node, and MutationObserver that listens for Dom changes.
  • Macro tasks include the execution of script scripts, setTimeout, setInterval, setImmediate, and other timed events, such as I/O operations, UI rendering, and so on.

8. What is an execution stack

You can think of the execution stack as a store of function callsThe stack structure, follow the first in, then out principle.When executing the JS code, according to the principle of first in, then out, the last function will pop up the stack first, as you can see,fooFunction, and when it’s done, it pops off the stack.

In normal development, you can find traces of the execution stack in the error report:

function foo() {
  throw new Error('error')}function bar() {
  foo()
}
bar()
Copy the code

You can see the error infooThe function,fooAgain, the function isbarFunction. When recursion is used, there are functions that can be stored by the stacklimitIf you store too many functions and they are not released, the stack will explode

function bar() {  bar()}bar()
Copy the code

9. What is the difference between an Event Loop in Node and one in the browser? Process. nextTick Execution sequence?

An Event Loop in Node is a completely different thing than an Event Loop in a browser.

Node’s Event Loop is divided into six stages, which are followed byThe orderRun again and again. Whenever a phase is entered, the function is retrieved from the corresponding callback queue and executed. When the queue is empty or the number of callbacks executed reaches a threshold set by the system, the next stage is entered.

Timers: Enter the event loop for the first time, starting with Timers. This phase will determine whether there are expired timer callbacks (including setTimeout and setInterval). If there are, all expired timer callbacks will be executed. After the execution, if the corresponding microtasks are triggered in the callback, all microtasks will be executed. Enter the Pending Callbacks phase after executing the microtasks.

(2) Pending Callbacks: Execute I/O callbacks that are delayed until the next iteration of the loop (system call-related callbacks).

(3) Idle/Prepare: for internal use only.

(4) Poll stage:

  • When the callback queue is not empty: the callback is executed. If the corresponding microtask is triggered in the callback, the execution time of the microtask here is different from that in other places. The microtask is not executed after all the callbacks are executed, but after each callback is executed. After all the callbacks are executed, the following becomes the case.
  • When the callback queue is empty (no callback or all the callbacks are executed) : If timers such as setTimeout, setInterval, and setImmediate do not perform, the polling phase ends and the Check phase enters. Otherwise, it blocks and waits for any ongoing I/O operations to complete, and executes the appropriate callbacks immediately until all callbacks are completed.

(5) Check (query phase) : Check whether there is a callback related to setImmediate, if there is, all the callbacks are executed, and after the execution, if the corresponding microtasks are triggered in the callback, all the microtasks are executed, and then enter the Close callbacks phase after the execution of the microtasks.

(6) Close callbacks: Perform some Close callbacks, such as socket.on(‘ Close ‘,…) And so on.

Here’s an example. First, in some cases, the order of execution of the timer is actually random

setTimeout(() = > {    console.log('setTimeout')}, 0)setImmediate(() = > {    console.log('setImmediate')})
Copy the code

For the above code, setTimeout may be executed before or after

  • First of all,setTimeout(fn, 0) === setTimeout(fn, 1), which is determined by the source code
  • There is also a cost to entering the event loop, and if it takes more than 1ms at the time of preparation, it will be executed directly in the Timer phasesetTimeoutThe callback
  • So if the preparation time is less than 1ms, then issetImmediateThe callback is executed first

Of course, in some cases, their execution order must be fixed, such as the following code:

const fs = require('fs')
fs.readFile(__filename, () = > {
    setTimeout(() = > {
        console.log('timeout');
    }, 0)
    setImmediate(() = > {
        console.log('immediate')})})Copy the code

In the code above, setImmediate always executes first. Because the two pieces of code are written in the IO callback, the IO callback is performed in the poll phase, and when the queue is empty after the callback is completed, the setImmediate callback is found to exist, so it directly goes to the check phase to perform the callback.

The above is a macroTask execution, for microTask, it will be completed before each of the above phasesemptyMicrotask queue, the Tick in the figure below represents microTask

setTimeout(() = > {
  console.log('timer21')},0)
Promise.resolve().then(function() {
  console.log('promise1')})Copy the code

For the above code, the output is the same as in the browser, microTask always executes before MacroTask.

Finally, in Node, process.nextTick is separate from the Event Loop. It has its own queue. And executes before other MicroTasks.

setTimeout(() = > {
 console.log('timer1')
 Promise.resolve().then(function() {
   console.log('promise1')})},0)
process.nextTick(() = > {
 console.log('nextTick')
 process.nextTick(() = > {
   console.log('nextTick')
   process.nextTick(() = > {
     console.log('nextTick')
     process.nextTick(() = > {
       console.log('nextTick')})})})Copy the code

For the above code, the nextTick is always printed out first.

10. What is the process of event triggering

There are three stages of event triggering:

  • windowPropagates to the event trigger, which is triggered when a registered capture event is encountered
  • The event that triggers registration when propagated to the event trigger
  • From the event trigger towindowPropagated, triggered by a bubbling event upon registration

Event firing generally occurs in the above order, but there are exceptions. If both the bubble and capture events are registered for a child node in a body, the event firing occurs in the order in which they were registered.

// The following will print bubbles first and then capture
node.addEventListener(
  'click'.event= > {
    console.log('bubble')},false
)
node.addEventListener(
  'click'.event= > {
    console.log('capture')},true
)
Copy the code

Events are typically registered using addEventListener, which takes a Boolean value or an object as the third argument. The default value is False for the Boolean useCapture parameter, which determines whether the registered event is a capture event or a bubble event. For object arguments, you can use the following properties:

  • capture: Boolean values, anduseCaptureRole as
  • once: Is a Boolean valuetrueIndicates that the callback will be called only once and the listener will be removed
  • passive: Boolean, indicating that it will never be calledpreventDefault

In general, if you only want the event to be triggered at the target, you can use stopPropagation to prevent further propagation of the event. StopPropagation is usually thought to prevent events from bubbling, but it can also prevent capturing events.

StopImmediatePropagation also prevents an event, but it also prevents the event target from executing other registered events.

node.addEventListener(
  'click'.event= > {
    event.stopImmediatePropagation()
    console.log('bubble')},false
)
// Clicking node will only execute the above function. This function will not execute
node.addEventListener(
  'click'.event= > {
    console.log('capture')},true
)
Copy the code

9. Browser garbage collection mechanism

1. What is the garbage collection mechanism of V8

V8 realizes accurate GC, and GC algorithm adopts generational garbage collection mechanism. Therefore, V8 divides memory (the heap) into young and old.

(1) Cenozoic algorithm

Exploiture GC algorithm is used to avenge an object in the Cenozoic.

In the new generation space, the memory space is divided into two parts, which are From space and To space. Of these two Spaces, one must be used and the other free. The newly allocated objects are put into the From space, and when the From space is full, the new generation GC starts. The algorithm checks for surviving objects in the From space and copies them into the To space, and destroys inanimate objects. When replication is complete, the From space and To space are interchanged, and GC is finished.

(2) Old generation algorithm

The objects in the old generation generally have a long life and a large number of objects. Two algorithms are used, namely, the marker clearing algorithm and the marker compression algorithm.

Let’s start with what happens when an object appears in an old generation space:

  • Be insane. If an object in the new generation has experienced the Scavenge algorithm, it will move the object from the new generation space to the old generation space.
  • The size of objects in the To space exceeds 25%. In this case, objects are moved from the new generation space to the old generation space in order not to affect memory allocation.

The space in the old generation is very complex, there are several Spaces as follows

enum AllocationSpace {
  // TODO(v8:7464): Actually map this space's memory as read-only.
  RO_SPACE,    // Immutable object space
  NEW_SPACE,   // The space used for the GC replication algorithm
  OLD_SPACE,   // Old generation resident object space
  CODE_SPACE,  // Old code object space
  MAP_SPACE,   // The old map object
  LO_SPACE,    // Old generation large space object
  NEW_LO_SPACE,  // New generation of large space objects
  FIRST_SPACE = RO_SPACE,
  LAST_SPACE = NEW_LO_SPACE,
  FIRST_GROWABLE_PAGED_SPACE = OLD_SPACE,
  LAST_GROWABLE_PAGED_SPACE = MAP_SPACE
};
Copy the code

In the old generation, the marker clearing algorithm is started first in the following cases:

  • When a space is not partitioned
  • The number of objects in the space exceeds a certain limit
  • Space does not guarantee that objects in the new generation will move into the old generation

In this phase, all objects in the heap are traversed, live objects are marked, and all unmarked objects are destroyed when the marking is complete. When marking large pairs of memory, it can take hundreds of milliseconds to complete a single marking. This can lead to some performance problems. To address this, in 2011, V8 switched from the stop-the-world flag to the incremental flag. During incremental markup, GC breaks down the markup work into smaller modules, allowing THE JS application logic to execute for a while between modules without causing the application to stop. But in 2018, THERE was another major breakthrough in GC technology, called concurrent tagging. This technique allows GC to scan and tag objects while allowing JS to run.

Clearing objects will cause heap memory fragmentation, when fragmentation exceeds a certain limit will start compression algorithm. During compression, live objects are moved to one end until all the objects have been moved and then the unwanted memory is cleared.

2. What operations cause memory leaks?

  • The first is when an undeclared variable is used and a global variable is accidentally created, leaving it in memory unrecyclable.
  • The second case is when you set the setInterval timer and forget to cancel it. If the loop function has a reference to an external variable, the variable will remain in memory and cannot be reclaimed.
  • In the third case, we get a reference to a DOM element, and the element is deleted. Since we keep the reference to the element, it cannot be reclaimed.
  • The fourth is the unreasonable use of closures, which causes some variables to remain in memory.