Skip to main content

浏览器是如何工作的

浏览器的主要功能

浏览器的主要功能是呈现从服务器中请求的网络资源,资源通常是 HTML 文档,但也可能是 PDF、图片或其他一些类型的内容。资源的位置由用户使用 URI (统一资源标识符)指定。

URI 和 URL 的区别?

URL 就是一种特定的 URI ,URI可以分为相对路径和绝对路径,URL 只能表示绝对路径。

HTML 和 CSS 规范指定了浏览器解释和显示 HTML 文件的方式。 这些规范由网络标准组织 W3C(万维网联盟)进行维护。

各个浏览器界面之间有许多共同点。常见的界面元素包括:

  1. 用于插入 URI 的地址栏
  2. “后退”和“前进”按钮
  3. 书签选项
  4. 用于刷新或停止加载当前文档的刷新和停止按钮
  5. 用于转到首页的“主页”按钮

浏览器的高层结构

浏览器的主要组件包括:

  1. 用户界面 :包括地址栏、前进/后退按钮、书签菜单等。除了显示所请求网页的窗口,浏览器的各个部分都会显示。
  2. 浏览器引擎 :在界面和呈现引擎之间编组操作。
  3. 呈现引擎 :负责显示所请求的内容。例如,如果请求的内容是 HTML,呈现引擎会解析 HTML 和 CSS,并将解析后的内容显示在屏幕上。
  4. 网络 :适用于 HTTP 请求等网络调用,在独立于平台的接口后为不同平台使用不同的实现。
  5. 界面后端 :用于绘制基本 widget,如组合框和窗口。此后端公开了与平台无关的通用接口。在其底层使用操作系统界面方法。
  6. JavaScript 解释器 。用于解析和执行 JavaScript 代码。
  7. 数据存储 。这是一个持久性层。浏览器可能需要在本地保存各种数据,例如 Cookie。浏览器还支持 localStorage、IndexedDB、WebSQL 和 FileSystem 等存储机制。

渲染引擎

渲染引擎用于渲染浏览器屏幕上的内容,不同的浏览器使用不同的渲染引擎:Internet Explorer 使用的是 Trident,Firefox 使用的是 Gecko,Safari 使用的是 WebKit。Chrome 和 Opera(版本 15)均使用 Blink,它是 WebKit 的一个分支。

WebKit 是一个开放源代码呈现引擎,最初是面向 Linux 平台的引擎,后来被 Apple 修改为支持 Mac 和 Windows。 如需了解详情,请参阅 webkit.org

  1. 解析 HTML:渲染引擎开始解析 HTML 文档,将元素转换为 DOM 树中的 DOM 节点。DOM树是一个表示HTML文档结构的对象树。
  2. 解析 CSS: 引擎会解析外部 CSS 文件和样式元素中的样式数据,在 HTML 中将样式信息和视觉指令一并设置为另一个树,即 CSSOM 树。
  3. 生成渲染树: 浏览器将 DOM 树和 CSSOM 树结合起来,生成渲染树,渲染树中的每个节点都对应一个带有视觉属性(如颜色和尺寸)的矩形。节点顺序决定了他们在屏幕上的显示顺序。
  4. 布局阶段: 渲染树构建完成后进入布局阶段,需要为每个节点提供在屏幕上出现的确切位置和大小。
  5. 绘制: 浏览器遍历渲染树,使用 UI 后端层绘制每个节点。

为了提供更好的用户体验,渲染引擎会尝试尽快在屏幕上显示内容。它不必等到所有 HTML 解析完毕之后,才会开始构建呈现树和设置布局。 系统会解析并显示部分内容,同时处理不断来自网络的其余内容,这种机制被称为"增量渲染"或"渐进渲染"。

重排重绘

"增量渲染"的优点是可以更快地向用户展示页面的内容,提供更好的用户体验。但是,如果后续接收到的数据导致DOM树、CSSOM树或渲染树的改变,浏览器可能需要重新布局和绘制,这可能会导致页面的重新渲染,也被称为"重排"或"重绘"。

重排Reflow

定义

DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器根据各种样式来计算并根据计算结果将元素放到它该出现的位置,这个过程称之为reflow

触发Reflow

当你增加、删除、修改 DOM 结点时,会导致 Reflow 或 Repaint

当你移动 DOM 的位置,或是搞个动画的时候

当你修改 CSS 样式的时候

当你 Resize 窗口的时候(移动端没有这个问题),或是滚动的时候

当你修改网页的默认字体时候(影响比较大,性能问题)

重绘Repaint

定义

当各种盒子的位置、大小以及其他属性,例如颜色、字体大小等确定下来后,浏览器于是便把这些元素都按照各自的特性绘制了⼀遍,于是页面的内容出现了,这个过程称之为 repaint 。即页面需要呈现的内容,⼀起画到屏幕上。

触发Repaint

DOM改动

CSS改动

(重点)如何尽量减⼩Repaint?

比如页面有⼀个计算器,用户在输入框输入⼀些计算表达式,最后显示计算结果,然后把输入给隐藏掉。这⾥就有两个交互,先是⽤户输⼊,将输⼊隐藏掉,然后将结果显示出来。这两个交互呈现内容不⼀样,当然就需要Repaint,那怎么做

优化方法:(链接:https://juejin.cn/post/6976644294740279310)

  • 避免频繁使用 style,而是采用修改class的方式,预先在 CSS 中定义好可能的样式类,然后在 JavaScript 中只需要切换这些类。
  • 使用createDocumentFragment进行批量的 DOM 操作。
  • 对于 resize、scroll 等进行防抖/节流处理。
  • 添加 will-change: tranform ,让渲染引擎为其单独实现一个图层,当这些变换发生时,仅仅只是利用合成线程去处理这些变换,而不牵扯到主线程,大大提高渲染效率。当然这个变化不限于tranform, 任何可以实现合成效果的 CSS 属性都能用will-change来声明。

解析

解析文档意味着将其转换为代码可以使用的结构。解析结果通常是代表文档结构的节点树。这称为解析树或语法树。

所有可以解析的格式都必须包含确定性的语法,由词汇和语法规则组成。这称为与上下文无关的语法。解析以文档遵守的语法规则为基础对文档进行解析。

上下文无关语法(Context-Free Grammar,CFG)是一种用于描述某些类型计算机语言语法的形式语法。它是由一组产生式规则组成的,这些规则用于生成语言中的字符串。上下文无关语法的一个关键特性是,产生式规则的应用不依赖于字符串中的元素的上下文。

在上下文无关语法中,每个产生式规则都有一个单独的非终结符在左边,右边是由非终结符和终结符(或者只有终结符)组成的一个字符串。非终结符是语法结构的名称(例如,表达式、语句等),终结符是语言的基本符号(例如,关键字、操作符等)。

上下文无关语法在编程语言的设计和实现中扮演着重要的角色,因为大多数编程语言的语法都可以(至少大部分)被描述为上下文无关语法。

词法分析器和语法分析器

解析可以分为两个子过程:词法分析和语法分析。

词法分析是将输入内容拆分成多个标记( tokens )的过程,语法分析是应用语言语法规则,将与标记对应的节点添加到解析树中的过程。

词法分析器负责将输入内容分解成有效标记,而语法分析器负责根据语言规则分析文档结构,构建解析树。

解析过程是迭代进行的。通常,解析器(语法分析器)会向词法分析器请求一个新标记,并尝试将该标记与某条语法规则进行匹配。如果匹配了规则,就会将一个与标记对应的节点添加到解析树中,然后解析器会请求另一个标记。

翻译

在许多情况下,解析树不是最终产物。解析树会被翻译成其他形式。

解析器的类型

解析器有两种类型:自上而下解析器和自下而上解析器。

  • 自顶向下解析器 :这种解析器从语法的最高级别结构开始,尝试将输入匹配到这些结构。如果无法匹配,它会回溯并尝试其他可能的结构。最常见的自顶向下解析器是递归下降解析器和预测解析器。
  • 自底向上解析器 :这种解析器从输入的词元开始,尝试将它们组合成更高级别的结构。这种解析器的一个例子是LR解析器,它被广泛用于许多现代编译器中,如GCC和Clang。