浏览器工作原理

主要分为导航、获取数据、HTML解析、css解析、执行javaScript、渲染树几个步骤。

1.导航

DNS查询

DNS服务器类似于电话簿,里面包含公共的IP地址以及相关主机名数据库,我们输入一个域名,他能帮我们映射到对应的IP地址。(第一次查询某个网站的时候,IP地址会被缓存一段时间,所以DNS 查询只发生在我们第一次访问一个网站时)

TCP握手

当浏览器知道了网站的IP地址时,他会进行TCP三次握手(更准确的说是 SYN、SYN-ACK、ACK,因为 TCP 有三个消息传输,用于协商和启动两台计算机之间的TCP 会话)与持有资源的服务器建立连接。

第一次 浏览器向服务器发送一个 SYNC 消息,要求进行同步(浏览器:服务器,帮我建立一个连接)

第二次 服务器将回复一个 SYNC-ACK 消息(服务器:收到,我也需要你帮我打开一个连接)

第三次 浏览器将回复一个 ACK 信息(浏览器:我即将打开)

TCP连接(双向连接)已经通过3次握手建立,TLS协商可以开始。

TLS协商

对于通过https建立的安全连接,需要另外进行一次握手。这种握手(TLS协商)决定了哪个密码将被用于加密通信,验证服务器,并在开始实际的数据传输之前建立一个安全的连接。

在这一步骤中,浏览器和服务器之间还交换了一些信息

  • 客户端 hello 。浏览器向服务器发送一条信息,其中包括它所支持的TLS版本和密码套件,以及一串随机字节,称为 客户端随机数
  • 服务器 hello 和证书 。服务器发回一条信息,其中包括服务器的SSL证书、服务器选择的密码套件和服务器随机数,这是服务器生成的另一个随机字节串。
  • 认证。浏览器会向颁发证书的机构核实服务器的 SSL 证书。这样,浏览器就可以确定服务器就是它所说的那个人。
  • 预主密码 。浏览器会再发送一串随机的字节,称为主密钥,用浏览器从服务器的 SSL 证书上获取的公钥进行加密。主密码只能由服务器用私钥解密。
  • 使用私钥 。服务器解密预主密码
  • 创建会话密钥。浏览器和服务器从客户端随机数、服务器随机数和预主密码中生成会话密钥。
  • 客户端完成。浏览器向服务器发送一个消息,说它已经完成。
  • 服务器完成。服务器向浏览器发送一个消息,表示它也完成了。
  • 安全对称加密实现。握手完成,通信可以继续使用会话密钥。

2.获取数据

HTTP请求

在我们与服务器建立安全连接后,浏览器将发送一个初始的 HTTP GET 请求。首先,浏览器将请求页面的 HTML 文件。它将使用 HTTP 协议来做这件事。

HTTP(超文本传输协议)是一个获取资源的协议,如HTML文件。它是网络上任何数据交换的基础,它是一个客户-服务器协议,这意味着请求是由接收者发起的,通常是网络浏览器

HTTP 响应

一旦服务器收到请求,它将对其进行处理并回复一个 HTTP 响应。在响应的正文中,我们可以找到所有相关的响应头和我们请求的HTML文档的内容,然后HTMl文件会引入不同的css和js文件

3.HTML解析

当浏览器接收到服务器的相应数据之后,就开始了解析这些数据,解析将由浏览器引擎完成

浏览器引擎是每个主要浏览器的核心组件,它的主要作用是结合结构 (HTML) 和样式 (CSS),以便它可以在我们的屏幕上绘制网页。 它还负责找出哪些代码片段是交互式的。

常用浏览器引擎

Gecko :火狐

WebKit :谷歌、safari

**Blink (基于 Chromium):**uc、百度、Edge

HTML 解析涉及两个步骤:词法分析树构造(构建称为 DOM 树的东西)。

词法分析

将一些输入转换成标签,词法分析过程结束时的结果是一系列 0 个或多个以下标签:DOCTYPE、开始标签 (<tag>)、结束标签(</tag>)、自闭合标签 (<tag/>) 、属性名称、值、注释、字符、文件结尾或元素中的纯文本内容。

构建DOM

基于先前解析的标签创建**树状结构。**

解析器从上到下逐行工作。 当解析器遇到非阻塞资源(例如图像)时,浏览器会向服务器请求这些图像并继续解析。 另一方面,如果它遇到阻塞资源(CSS 样式表、在 HTML 的 <head> 部分添加的 Javascrpt 文件或从 CDN 添加的字体),解析器将停止执行,直到所有这些阻塞资源都被下载。 这就是为什么,如果你正在使用 Javascript,建议在 HTML 文件的末尾添加 <script> 标签,或者如果你想将它们保留在 <head> 标签中,你应该向它们添加 defer 或 async 属性( async 允许在下载脚本后立即执行异步操作,而 defer 只允许在整个文档被解析后执行。)。

预加载器 & 使页面更快

主要就是在HTML在需要使用他引入的文件时,文件已经提前加载完毕(正常情况下是执行那一行才才去加载)

4.css解析

和构建DOM数类似,构建CSSOM

5.执行JavaScript

在解析 CSS 并创建 CSSOM 的同时,还会下载其他资产,包括 JavaScript 文件。 这要归功于我们在之前文章中提到的预加载器。

预加载器就像一个解析器,它在主解析器处理 HTML 代码时扫描 HTML 文件。 它的作用是查找样式表、脚本或图片(也需要从服务器检索)等资源并请求它们。 希望在解析 HTML 时,这些资源已经下载并准备好进行处理。

当我们从服务器获取 Javascript 文件后,代码被解释、编译、解析和执行。 计算机无法理解 Javascript 代码,只有浏览器可以。 JS 代码需要被翻译成计算机可以使用的东西,这是 Javascript 浏览器引擎的工作(不要与浏览器引擎混淆)。 根据浏览器的不同,JS 引擎可以有不同的名称和不同的工作方式。

Javascript 引擎

作用:浏览器js引擎将代码转换成计算机能识别的东西。

常用js引擎

v8:谷歌、node

SpiderMonkey:火狐

JavaScriptCore:safari、macOS

ChakraCore:Edge

编译、解释、即时编译

编译: 在编译过程中,一个称为编译器的软件将用高级语言编写的代码一次性转换为机器代码。 创建一个目标文件,该文件可以在任何机器上运行。 采取这些步骤后,就可以执行代码了。

解释:在解释过程中,解释器逐行检查 Javascript 代码并立即执行。 没有进行编译,因此没有创建目标代码(代码的输出由解释器本身使用其内部机制创建)。 旧版本的 Javascript 使用这种类型的代码执行。

即时编译:即时编译是给定语言的解释器的一个特性,它试图同时利用编译和解释。 是在纯编译期间,代码是在执行之前被编译,然而在 JIT 编译中,代码在执行时(在运行时)被编译。 所以我们可以说源代码是动态转换为机器代码的。 较新版本的 Javascript 使用这种类型的代码执行。

简而言之,这三个过程可以总结为:

  • 编译器:编译代码
  • 解释器:运行代码
  • JIT 编译器:在运行代码时进行编译

JavaScript处理

当 Javascript 代码进入 Javascript 引擎时,它首先被解析。 这意味着代码被读取,并且在这种情况下,代码被转换为称为**抽象语法树** (AST) 的数据结构。 代码将被拆分成与语言相关的部分(如 functionconst 关键字),然后所有这些部分将构建抽象语法树。

构建 AST 后,它会被翻译成机器代码并立即执行,因为现代 Javascript 使用即时编译。 这段代码的执行将由 Javascript 引擎完成,利用称为"调用堆栈"的东西。

调用堆栈是解释器(如 Web 浏览器中的 JavaScript 解释器)跟踪其在调用多个函数的脚本中的位置的机制------当前正在运行的函数以及从该函数中调用的函数等。

6.渲染树

在解析阶段构建的树(DOM、CSSOM)被组合成一种叫做渲染树的东西。 这用于计算最终将绘制到屏幕上的所有可见元素的布局。 渲染树的目的是确保页面内容以正确的顺序绘制元素。 它将作为在屏幕上显示像素的绘画过程的输入。

结合 DOM 和 CSSOM

  • 浏览器将开始在 DOM 树的根部施展魔法并遍历每个可见节点。 一些节点,如脚本或元标记是不可见的,因此它们被忽略。 还有一些节点会被 CSS 隐藏(例如 display: "none" 属性),它们也会被忽略。 我们只对可见节点感兴趣,因为只有它们对屏幕上的输入有影响。
  • 对于在 DOM 中找到的每个可见节点,将在 CSSOM 中找到相应的规则并应用它们。

以上步骤的结果将是一个包含所有可见节点、内容和样式的渲染树

布局(回流)阶段

渲染树 包含有关显示哪些节点及其计算样式的信息,但不包含每个节点的尺寸或位置

接下来需要做的是计算这些节点在设备视口(浏览器窗口内)内的确切位置及其大小。 这个阶段称为重排, 浏览器在渲染树的根部开始这个过程并遍历它。

回流步骤不会只发生一次,而是每次我们更改 DOM 中影响页面布局的某些内容时,即使是部分更改,都会触发回流。 重新计算元素位置的情况示例如下:

  • 在 DOM 中添加或删除元素
  • 调整浏览器窗口大小
  • 更改元素的宽度、位置或使其浮动

绘画(重绘)阶段

在浏览器决定哪些节点需要可见并计算出它们在视口中的位置后,就可以在屏幕上绘制它们(渲染像素)了。 这个阶段也被称为光栅化阶段,浏览器将在布局阶段计算的每个盒子转换为屏幕上的实际像素。

就像布局阶段一样,绘画阶段不会只发生一次,而是每次我们改变屏幕上元素的外观时。 这些情况的例子是:

  • 改变元素的轮廓
  • 改变背景颜色
  • 改变不透明度或可见性

绘画意味着浏览器需要将元素的每个视觉部分绘制到屏幕上,包括文本、颜色、边框、阴影和替换元素(如按钮和图像),并且需要超快地完成。 为了确保重绘可以比初始绘制更快地完成,屏幕上的绘图通常被分解成几层 。 如果发生这种情况,则需要进行合成

分层和合成

合成是一种将页面的各个部分分成层的技术,分别绘制它们并在称为合成器线程的单独线程中合成为页面。 当文档的各个部分绘制在不同的层中并相互重叠时,合成是必要的,以确保它们以正确的顺序绘制到屏幕上并且内容被正确呈现。

相关推荐
王解6 小时前
Jest项目实战(4):将工具库顺利迁移到GitHub的完整指南
单元测试·github
油泼辣子多加6 小时前
2024年11月4日Github流行趋势
github
梓羽玩Python7 小时前
推荐一款用了5年的全能下载神器:Motrix!全平台支持,不限速下载网盘文件就靠它!
程序员·开源·github
小牛itbull13 小时前
ReactPress:重塑内容管理的未来
react.js·github·reactpress
鱼满满记21 小时前
1.6K+ Star!GenAIScript:一个可自动化的GenAI脚本环境
人工智能·ai·github
梦魇梦狸º1 天前
腾讯轻量云服务器docker拉取不到镜像的问题:拉取超时
docker·容器·github
Huazie1 天前
一篇搞定 Hexo Diversity 主题接入!支持多主题自由切换!
javascript·github·hexo
草明2 天前
Nginx 做反向代理,一个服务优先被使用,当无法提供服务时才使用其他的备用服务
运维·nginx·github
马里嗷2 天前
Puppeteer - 掌控浏览器自动化的开源利器
后端·github