# 1.宏观视角下的浏览器

## 01.Chrome架构：仅仅打开一个页面，为什么有四个进程

> 在谷歌浏览器随便打开一个页面，点击“选项”菜单，选择“更多工具”，点击“任务管理器”，这将打开Chrome的任务管理器的窗口，你会发现一个页面上有四个以上的进程。为什么会有四个进程呢？ 本章通过分析浏览器的进化史而展开探讨这个问题。\
> 开始之前，我们必须得了解一下这个`进程`与`线程`的概念。

### 线程 VS 进程

> `线程这个东西它是不能单独存在的，它是由进程来启动和管理的。`\
> `一个进程就是一个程序的运行实例`。
>
> `线程是依附于进程的，而进程中使用多线程并行处理能提升运算效率`。
>
> 总结，线程与进程之间的关系有以下四个特点： 1. 进程中任一线程执行出错，都会导致整个进程崩溃。 2. 线程之间共享进程的数据。\
> 3\. 当一个进程关闭之后，操作系统会回收进程所占用的内存。\
> 4\. 进程之间的内容都互相隔离。(如果进程之间需要进行数据的通信，这时候需要使用用于进程间通讯(IPC)机制了)。

### 单进程浏览器时代

> 早在07年之前，市面上的浏览器都是单进程的。单进程，顾名思义是指：浏览器的所有功能模块都运行在同一个进程里。\
> 如此多的功能模块运行在一个进程里，导致单进程浏览器`不稳定`、`不流畅`、`不安全`。\
> 具体的表现就不说了，总之体验非常差，于是进入了“多线程浏览器”时代。

### 多进程浏览器时代

> * 多进程浏览器由于进程相互隔离，所以当一个页面或者插件崩溃的时候，影响的仅仅是当前的页面进程或者插件过程。这就完美解决了页面或者插件崩溃而导致的整个浏览器崩溃问题。JS的渲染若出现问题，影响的同样是当前的渲染页面，没有响应的仅对当前页面。而且在多进程浏览器时代，当关闭一个页面的时候，整个渲染进程会被关闭，该进程占用的内存都会被系统回收，这样也就轻松解决了浏览器页面的内存泄露问题。   &#x20;
> * 此外有关安全方面的问题：使用多线程架构可以使用`安全沙箱`。 &#x20;
>
> 可以把沙箱看成是操作系统给进程上了一把锁，沙箱里面的程序可以运行，但是不能在硬盘上写入任何数据，也不能在敏感位置读取任何数据(例如文档和桌面)，Chrome把插件进程和渲染进程锁在沙箱里面，这样即使在渲染进程或者插件进程里面执行了恶意程序，恶意程序也无法突破沙箱去获取系统权限。

### 目前多进程架构

> 最新的Chrome进程架构：Chrome浏览器包括：`1个浏览器(Brower)主进程，1个GPU进程、一个网络(NetWork)进程、多个渲染进程和多个插件进程`。\
> 虽然多进程模型提升了浏览器的稳定性、流畅性、安全性，但是同样也会不可避免带来一些问题：
>
> * `更高的资源占用` ：因为每个进程都会包含公共基础结构的副本（如JavaScript运行环境），这意味着浏览器会消耗更多的资源。 &#x20;
> * `更复杂的体系架构`：浏览器各模块之间耦合性高、扩展性差等问题，会导致现在的架构已经很难适应新的需求。

### 未来面向服务的架构(SOP)

> 为了解决这些问题，2016年，Chrome团队使用“面向服务的架构“（SOP）思想设计了新的Chrome架构，这也是现阶段Chrome团队的一个主要任务。

## 02｜TCP协议：如何保证页面文件能被完整的送达浏览器

> 在衡量Web页面性能的时候有一个重要的指标叫"FP(First Paint)",是指从页面加载到首次开始绘制的时长。其中影响FP的一个重要因素就是`网络加载速度`。
>
> 要优化网络加载速度，需要对网络有充分的了解，这一节重点介绍`在Web世界中的TCP/IP是如何工作的`。
>
> 在网络中，一个文件通常会被拆分为很多数据包来进行传输，而数据包在传输过程中有很大概览丢失或者出错，那么如何保证页面文件能被完整地送达浏览器？
>
> ### 一个数据包的“旅程”
>
> 1. IP:把数据包送达目的主机\
>    计算机的地址称为IP地址，访问任何网站实际上只是你的计算机向另外一台计算机请求信息。\
>    当从主机A向主机B发送数据(即发送数据包)，传输前，数据包会被附加上主机A和主机B的IP地址信息，这些信息会被封到一个叫做IP头的数据结构里，在这个IP头中包含IP数据包开头的信息(IP版本、源IP地址、目标地址、生存时间等信息)，于是数据包从主机A发送到主机B。
> 2. UDP:把数据包送达应用程序 IP通过IP地址信息把数据包发送给指定的电脑，而UDP通过端口号把数据包发给正确的程序。 UDP发送数据，有各种因素会导致数据包出错，虽然UDP可以校验数据是否正确，但是`UDP不提供重发机制`，只是丢弃当前的包，且UDP在发送之后无法知道能否到达目的地。\
>    `UDP不能保证数据可靠性，但是传输速度却非常快`，因此UDP应用在一些关注速度但不那么严格要求数据完整性的领域，例如：在线视频、互动游戏等。
> 3. TCP:把数据完整的送达应用程序 TCP(Transmission Control Protocol,传输控制协议)：他是一种面向连接的、可靠的、基于字节流的传输层通信协议。相对于UDP而言：
> 4. 对于数据包丢失情况，提供重传机制。 &#x20;
> 5. TCP引入数据包排序机制，用来保证把乱序的数据包组合成一个完整的文件。&#x20;
>
>    **完整的TCP连接过程**
>
>    我们现在已经知道TCP单个数据包的传输流程和UDP流程差不多，不同在于，通过TCP头信息可以保证一块大的数据传输的完整性。&#x20;
>
>    一个完整的TCP连接过程，其生命周期包括了“建立连接“、”数据传输“、”断开连接“三个阶段。
> 6. 建立连接阶段：这个阶段通过“三次握手”来建立客户端和服务器之间的连接。 &#x20;
> 7. 数据传输阶段：在该阶段，接收端需要对每个数据包进行确认操作。接收端应该在接收数据后要发送确认数据包给发送端，若发送端没有接收到这个确认，则判断数据包丢失，并触发发送端的重发机制。 &#x20;
> 8. 断开连接阶段：数据传输完毕，终止连接，通过最后一个阶段“四次挥手”来保证双方都能断开连接。

## 03｜HTTP请求流程：为什么很多站点第二次打开速度会很快？

> 首先的首先我们知道：HTTP协议建立在TCP连接基础之上的。`HTTP是一种允许浏览器向服务器获取资源的协议，是Web的基础。HTTP是浏览器使用最广的协议`。
>
> 简单说说HTTP和TCP的关系：浏览器使用HTTP协议作为`应用层协议`，用来封装请求的文本信息，并使用TCP/IP作为`传输层协议`将它发到网路上,所以HTTP工作前，需要通过TCP与服务器建立连接，也就是说：`HTTP的内容是通过TCP的传输数据阶段来实现的`。

### 浏览器端发起HTTP请求流程

> 如果在浏览器地址栏里输入：<https://www.liugezhou.online> 这个网址后,浏览器这个庞然大物，它的背后都做些什么呢？

* 构建请求

  > 首先浏览器构建请求行信息，构建好之后，浏览器准备发起网路请求。
* 查找缓存

  > 在准备发起网路请求阶段，浏览器偷偷的在它的缓存中查询是否有要请求的资源。\
  > 若有：拦截请求，返回资源副本，直接结束请求。\
  > 若缓存查找失败：继续下一步。
* 准备IP地址和端口号

  > 这个IP地址和端口号的获取，肯定是通过域名与其映射，即“域名系统”，也就是我们熟知的DNS。 于是，浏览器第一步会请求DNS返回域名对应的IP，如果没有特别指明端口号，则默认为80。 (浏览器提供了DNS数据缓存服务，若缓存过也就不会去请求，直接解析。从而减少一次网络请求)
* 等待TCP队列

  > 拿到IP地址与端口号后，还需要在TCP队列中排队才能建立TCP连接。\
  > 这是因为：Chrome有个机制，同一个域名同时最多只能建立6个TCP连接，若此刻同时有10个请求发生。则四个会进入TCP队列进行排队。 当然，若当前请求数量少于6个，则会直接进入下一步。
* 建立TCP连接&#x20;

  > 建立TCP连接，上一节我们已经知道，一个完整的TCP连接过程包括“建立连接”、“数据传输”、“断开连接“三个阶段。
* 发送HTTP请求

  > HTTP请求是在TCP连接的数据传输阶段工作的，这个时候浏览器向服务器发送请求行，它包括请求方法、请求URI、HTTP版本协议。，HTTP中的数据在这个通信过程中传输。

### 服务器端处理HTTP请求流程

> 这里可以在命令行中输入`curl -i https://www.google.com`来查看返回请求数据。 (-i 返回响应行、响应头和响应体信息。 -I 不返回响应体。)\
> 返回网站的HTTP协议、Connection、Location、Cache-Control等信息。
>
> 通常情况，一旦服务器向客户端返回了请求数据，它就要关闭TCP连接，但是如果浏览器或者服务器设置了`Connection:keep-alive`，那么TCP连接在发送后将仍保持打开状态。`保持TCP连接可以省去下次请求时需要建立连接的时间，提升资源加载速度`。

### 问题解答

1. 为什么很多站点第二次打开速度会很快？

   > 主要原因肯定是第一次加载页面的过程中，缓存了一些数据(从上面的过程分析，我们知道`DNS缓存`和`页面资源缓存`这两块数据是会被浏览器缓存起来的).\
   > 网站把很多资源都缓存到了本地，浏览器缓存直接使用本地副本来回应请求，而不会产生真实的网络请求，从而节省了时间。
2. 登录状态是如何保持的&#x20;

   > 简单地说，如果服务器端发送的响应头内有 Set-Cookie 的字段，那么浏览器就会将该字段的内容保持到本地。当下次客户端再往该服务器发送请求时，客户端会自动在请求头中加入 Cookie 值后再发送出去。服务器端发现客户端发送过来的 Cookie 后，会去检查究竟是从哪一个客户端发来的连接请求，然后对比服务器上的记录，最后得到该用户的状态信息。

## 04｜导航流程：从输入URl到页面展示，这中间发生了什么

> 流程开始前，回顾下浏览器进程、网络进程、渲染进程的各自主要职责：
>
> * 浏览器进程：主要负责`用户交互`、`子进程管理`和`文件储存`等功能。 &#x20;
> * 网络进程：面向渲染进程或浏览器进程提供`网络资源下载`。 &#x20;
> * 渲染进程：将HTML、CSS、JS、图片等资源解析为可以显示和交互的页面。

### 过程大致描述

> * 首先，用户从浏览器进程中输入请求信息。 &#x20;
> * 然后，网络进程发起URL请求。&#x20;
> * 服务器响应URL请求后，浏览器进程开始准备渲染进程。&#x20;
> * 渲染进程准备好以后，需要先向渲染进程提交页面数据，这称之为文档提交阶段。 &#x20;
> * 渲染进程接收到文档信息之后，便开始解析页面和加载子资源，完成页面的渲染。
>
>   这其中，用户发出URL请求到页面开始解析的过程，就叫做导航。

### 从输入URL到页面展示--过程细节

> * 响应数据类型处理：根据服务端返回的`Content-Type`字段来决定如何显示响应体的内容。
> * 同一站点下的多个页面会运行在一个渲染进程中。

### “从输入 URL 到页面展示，这中间发生了什么？”(留言总结)

> 1. 用户输入url并回车·
>    1. 浏览器进程检查url，组装协议，构成完整的url
>    2. 浏览器进程通过进程间通信（IPC）把url请求发送给网络进程
>    3. 网络进程接收到url请求后检查本地缓存是否缓存了该请求资源，如果有则将该资源返回给浏览器进程
>    4. 如果没有，网络进程向web服务器发起http请求（网络请求），请求流程如下：
>
>       5.1 进行DNS解析，获取服务器ip地址，端口
>
>       5.2 利用ip地址和服务器建立tcp连接
>
>       5.3 构建请求头信息
>
>       5.4 发送请求头信息
>
>       5.5 服务器响应后，网络进程接收响应头和响应信息，并解析响应内容
>    5. 网络进程解析响应流程；
>
>       6.1 检查状态码，如果是301/302，则需要重定向，从Location自动中读取地址，重新进行第4步 &#x20;
>
>       6.2 200响应处理：&#x20;
>
>       &#x20; 检查响应类型Content-Type，如果是字节流类型，则将该请求提交给下载管理器，该导航流程结束，不再进行后续的渲染，如果是html则通知浏览器进程准备渲染进程准备进行渲染。
>    6. 准备渲染进程
>
>       7.1 浏览器进程检查当前url是否和之前打开的渲染进程根域名是否相同，如果相同，则复用原来的进程，如果不同，则开启新的渲染进程
>    7. 传输数据、更新状态
>
>       8.1 渲染进程准备好后，浏览器向渲染进程发起“提交文档”的消息，渲染进程接收到消息和网络进程建立传输数据的“管道”
>
>       8.2 渲染进程接收完数据后，向浏览器发送“确认提交”
>
>       8.3 浏览器进程接收到确认消息后更新浏览器界面状态：安全、地址栏url、前进后退的历史状态、更新web页面。

## 05｜渲染流程(上)：HTML、CSS和JavaScript，是如何变成页面的

> 按照渲染的时间顺序，渲染流水线可分为以下几个构建阶段：\
> `构建DOM树`、`样式计算`、`布局阶段`、`分层`、`绘制`、`光栅化`、`合成`。 本节主要讨论前三个阶段。

### 构建DOM树

> 因为浏览器无法直接理解和使用 HTML，所以需要将 HTML 转换为浏览器能够理解的结构——DOM 树。 DOM树和HTML内容几乎一样，但和HTML不同的是：DOM是保存在内存中的树结构。

### 样式计算

> 1. 把CSS转换为浏览器能够理解的结构。
> 2. 转换样式表中的属性值，使其标准化。  &#x20;
>
>    「例如rem -> px, red -> rgb(255,0,0),bold -> 700」 &#x20;
> 3. 计算出DOM树中每个节点的具体样式。 &#x20;
>
>    「CSS继承：每个DOM节点都包含有父节点的样式」 &#x20;
>
>    「CSS层叠：它在 CSS 处于核心地位，定义了如何合并来自多个源的属性值的算法」 &#x20;
>
>    「样式来源：如果一个元素不提供任何样式，默认使用的是UserAgent样式---浏览器提供的一组默认样式」。

### 布局阶段

> 内容： 布局阶段是根据DOM树和样式计算出元素的几何位置。 1. 创建布局树「构建一颗只包含可见元素的布局树」\
> 2\. 布局计算
>
> 「在执行布局操作的时候，会把布局运算的结果重新写回布局树中，所以布局树既是输入内容也是输出内容，这是布局阶段一个不合理的地方，因为在布局阶段并没有清晰地将输入内容和输出内容区分开来。针对这个问题，Chrome 团队正在重构布局代码，下一代布局系统叫 `LayoutNG`，试图更清晰地分离输入和输出，从而让新设计的布局算法更加简单。」

## 06|渲染流程(下)：HTML、CSS和JavaScript，是如何变成页面的

### 分层

> 为了生成一些复杂效果(3D变换、页面滚动、z轴排序等)，渲染引擎还需要为特定的节点生成专用的图层，生成一颗对应的图层树.
>
> * 并不是布局树的每个节点都包含一个图层，如果一个节点没有对应的层，那么这个节点就从属于父节点的图层.  &#x20;
> * 素有了层叠上下文的属性或者需要被剪裁，满足这任意一点，就会被提升成为单独一层。

### 绘制

> 一个图层的绘制拆分成很多小的绘制指令，然后再把这些指令按照顺序组成一个`待绘制列表`。「可在浏览器开发者工具的Layers中查看。」

### 栅格化操作

> 所谓栅格化，是指将图块转换为位图。\
> 栅格化过程都会使用 GPU 来加速生成，使用 GPU 生成位图的过程叫快速栅格化，或者 GPU 栅格化，生成的位图被保存在 GPU 内存中.

### 合成和显示

> 一旦所有图块都被光栅化，合成线程就会生成一个绘制图块的命令——“DrawQuad”，然后将该命令提交给浏览器进程。经过浏览器就会显示出页面。
>
> 一个完整的渲染流程大致可总结为如下：
>
> * 渲染进程将 HTML 内容转换为能够读懂的 DOM 树结构。&#x20;
> * 渲染引擎将 CSS 样式表转化为浏览器可以理解的 styleSheets，计算出 DOM 节点的样式。 &#x20;
> * 创建布局树，并计算元素的布局信息。对布局树进行分层，并生成分层树。 &#x20;
> * 为每个图层生成绘制列表，并将其提交到合成线程。 &#x20;
> * 合成线程将图层分成图块，并在光栅化线程池中将图块转换成位图。 &#x20;
> * 合成线程发送绘制图块命令 DrawQuad 给浏览器进程。浏览器进程根据 DrawQuad 消息生成页面，并显示到显示器上。

### 相关概念

#### 重排(更新了元素的几何属性)

> 使用CSS或者JS使元素的几何位置发生了改变，例如改变元素的宽度、高度等，这会使得浏览器触发重新布局、解析之后的一系列子阶段，这个过程就是重排。无疑，重排需要更新完整的渲染流水线，所以开销是最大的。

#### 重绘(更新元素的绘制属性)

> 比如改变了元素的背景色，这会触发浏览器进行重绘之后的操作。相较于重排操作，重绘省去了布局和分层阶段，所以执行效率会比重排操作要高一些。
>
> #### 直接合成阶段
>
> 那如果你更改一个既不要布局也不要绘制的属性，会发生什么变化呢？渲染引擎将跳过布局和绘制，只执行后续的合成操作，我们把这个过程叫做合成. 例如CSS的transform实现的动画效果，可以避开重排和重绘阶段，相对于重绘和重排，合成能大大提升绘制效率。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://liugezhou.gitbook.io/liugezhou/hong-guan-shi-jiao-xia-de-liu-lan-qi/1.-hong-guan-shi-jiao-xia-de-liu-lan-qi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
