现代浏览器工作原理(一)

这些天在考虑选择什么主题在即将来临的公司技术分享会上进行分享。思来想去,也没找到什么比较好的主题。逆向?已经有人分享过了...框架?不是针对特定需求的框架,介绍起来感觉也没有太大的意义...

恍惚间,想起之前@展哥在调高考真题Hybrid页面时,似乎在前端代码方面遇到一些麻烦。于是,我就想到了UIWebView。就此进行思维发散,感觉可以介绍一下浏览器的工作原理。毕竟,iOS和前端同属于大客户端。对于iOS的同学,也算是对知识面的扩展吧。

于是,我查阅了一些与浏览器原理相关的资料。在这个过程中,找到很多优秀的资料。但是,大多数资料的组织结构,不是特别清晰。因此,我想借此机会,结合参考资料,来重新梳理一下浏览器的原理。由于浏览器的结构非常复杂,一篇文章想介绍清楚,真的太难。本文将使用总-分-总的形式,使用一系列文章来进行介绍。如有纰漏,欢迎纠正。

浏览器历史

1990年,蒂姆·伯纳斯·李开发了第一个网页浏览器WorldWideWeb,后改名为Nexus。WorldWideWeb浏览器支持早期的HTML标记语言,功能比较简单,只能支持文本、简单的样式表、电影、声音、图片等资源的显示。

1993年,马克·安德森领导的团开发了一个真正有影响力的浏览器Mosaic,这就是后来世界上最流行的浏览器Netscape Navigator

1995年,微软推出了闻名于世的浏览器Internet Explorer

1998年,Netscape公司开放Netscape Navigator源代码,成立了Mozilla基金会。

2003年,苹果公司发布了Safari浏览器。

2004年,Netscape公司发布了著名的开源浏览器Mozilla Firefox

2005年,苹果公司开源了浏览器中的核心代码,基于此发起了一个新的开源项目WebKit(Safari浏览器的内核)。

2008年, Google公司已WebKit为内核,创建了一个新的浏览器项目Chromium。以Chromium为基础,谷歌发布了Chrome浏览器。至于这两者的关系,可以简单地理解为:Chromium为实验版,具有众多新特性;Chrome为稳定版。

浏览器特性

现代浏览器的特性主要包含如下几部分:

  • 网络
    浏览器通过网络模块下载各种资源,如:HTML文档、JavaScript代码、样式表、图片、音频视频文件等。 网络模块是浏览器最重要的模块之一。
  • 资源管理
    浏览器通过高效的管理机制来管理网络资源和本地资源。比如如何避免重复下载资源、缓存资源等。
  • 网页浏览
    浏览器最核心的功能。浏览器通过网络下载资源,并从资源管理器获得资源,然后将其转化为可视化结果。
  • 多页面管理
    浏览器支持多页面浏览,因此支持多页面同时加载。浏览器需要多页面管理机制来解决例如多页面的相互影响和安全等问题。
  • 插件和扩展
    现代浏览器的重要特征。插件可以用来显示网页特定内容;扩展则是增加浏览器新功能的软件或压缩包。
  • 账户和同步
    现代软件的普遍特性。浏览器将用户的浏览信息,例如历史记录、书签等信息同步到服务器,提供多系统下的统一体验。
  • 安全机制
    现代软件的重要特性。浏览器的安全机制需要提供一个安全的浏览环境,例如:避免用户信息被窃取或破坏、防止浏览器被恶意代码攻破等。
  • 开发者工具
    开发者工具是浏览器提供给网页开发者的工具,可以帮助审查HTML元素、调试JavaScript代码、改善网页性能等。

浏览器结构

目前,常用的浏览器主要有:Chrome、IE(Edge)、Safari、Firefox等。不同的浏览器在结构方面虽然有所差异,但是整体的设计理念是相似的。因此,可以抽象得到如下图所示的参考结构:

浏览器的抽象分层结构图中将浏览器分成了以下8个子系统:

  • 用户界面(User Interface)
    用户界面主要包括工具栏、地址栏、前进/后退按钮、书签菜单、可视化页面加载进度、智能下载处理、首选项、打印等。除了浏览器主窗口显示请求的页面之外,其他显示的部分都属于用户界面。
    用户界面还可以与桌面环境集成,以提供浏览器会话管理或与其他桌面应用程序的通信。
  • 浏览器引擎(Browser Engine)
    浏览器引擎是一个可嵌入的组件,其为渲染引擎提供高级接口。
    浏览器引擎可以加载一个给定的URI,并支持诸如:前进/后退/重新加载等浏览操作。
    浏览器引擎提供查看浏览会话的各个方面的挂钩,例如:当前页面加载进度、JavaScript alert。
    浏览器引擎还允许查询/修改渲染引擎设置。
  • 渲染引擎(Rendering Engine)
    渲染引擎为指定的URI生成可视化的表示。
    渲染引擎能够显示HTML和XML文档,可选择CSS样式,以及嵌入式内容(如图片)。
    渲染引擎能够准确计算页面布局,可使用“回流”算法逐步调整页面元素的位置。
    渲染引擎内部包含HTML解析器。
  • 网络(Networking)
    网络系统实现HTTP和FTP等文件传输协议。 网络系统可以在不同的字符集之间进行转换,为文件解析MIME媒体类型。 网络系统可以实现最近检索资源的缓存功能。
  • JavaScript解释器(JavaScript Interpreter)
    JavaScript解释器能够解释并执行嵌入在网页中的JavaScript(又称ECMAScript)代码。 为了安全起见,浏览器引擎或渲染引擎可能会禁用某些JavaScript功能,如弹出窗口的打开。
  • XML解析器(XML Parser)
    XML解析器可以将XML文档解析成文档对象模型(Document Object Model,DOM)树。 XML解析器是浏览器架构中复用最多的子系统之一,几乎所有的浏览器实现都利用现有的XML解析器,而不是从头开始创建自己的XML解析器。
  • 显示后端(Display Backend)
    显示后端提供绘图和窗口原语,包括:用户界面控件集合、字体集合。
  • 数据持久层(Data Persistence)
    数据持久层将与浏览会话相关联的各种数据存储在硬盘上。 这些数据可能是诸如:书签、工具栏设置等这样的高级数据,也可能是诸如:Cookie,安全证书、缓存等这样的低级数据。

这里可能会产生一个疑问:功能相似的HTML解析器和XML解析器为什么前者划分在渲染引擎中,后者作为独立的系统?
原因:XML解析器对于系统来说,其功能并不是关键性的,但是从复用角度来说,XML解析器是一个通用的,可重用的组件,具有标准的,定义明确的接口。相比之下,HTML解析器通常与渲染引擎紧耦合。

渲染引擎

浏览器的组成模块众多,而渲染引擎则是浏览器中最重要的模块(渲染引擎有时候也被称为“浏览器内核”,这种说法并不严谨,不推荐使用)。目前,常见的渲染引擎有Trident、Gecko、WebKit等。下表所示为几种渲染引擎在不同浏览器中的应用:

渲染引擎 浏览器
Trident IE、Edge
Gecko Firefox
WebKit Safari、Chromium/Chrome

渲染引擎工作流程

如下图所示为渲染引擎的渲染流程示意图,其以HTML/JavaScript/CSS等文件作为输入,以可视化内容作为输出。

  1. Parsing HTML to Construct DOM Tree
    渲染引擎使用HTML解析器(调用XML解析器)解析HTML(XML)文档,将各个HTML(XML)元素逐个转化成DOM节点,从而生成DOM树。
    同时,渲染引擎使用CSS解析器解析外部CSS文件以及HTML(XML)元素中的样式规则。元素中带有视觉指令的样式规则将用于下一步,以创建另一个树结构:渲染树。

  2. Render Tree construction
    渲染引擎使用第1步CSS解析器解析得到的样式规则,将其附着到DOM树上,从而构成渲染树。
    渲染树包含多个带有视觉属性(如颜色和尺寸)的矩形。这些矩形的排列顺序就是它们将在屏幕上显示的顺序。

  3. Layout of Render Tree
    渲染树构建完毕之后,进入本阶段进行“布局”,也就是为每个节点分配一个应出现在屏幕上的确切坐标。

  4. Painting Render Tree
    渲染引擎将遍历渲染树,并调用显示后端将每个节点绘制出来。

渲染引擎组成模块

下图所示为渲染引擎工作流程中各个步骤所对应的模块,其中第1步和第2步涉及到多个模块,并且耦合程度较高。这样的设计会为了达到更好的用户体验,渲染引擎尽快将内容显示在屏幕上。它不必等到整个HTML文档解析完毕之后,就可以开始渲染树构建和布局设置。在不断接收和处理来自网络的其余内容的同时,渲染引擎会将部分内容解析并显示出来。

从图中可以看出,渲染引擎主要包含(或调用)的模块有:

  • HTML(XML)解析器
    解析HTML(XML)文档,主要作用是将HTML(XML)文档转换成DOM树。
  • CSS解析器
    将DOM中的各个元素对象进行计算,获取样式信息,用于渲染树的构建。
  • JavaScript解释器
    使用JavaScript可以修改网页的内容、CSS规则等。JavaScript解释器能够解释JavaScript代码,并通过DOM接口和CSSOM接口来修改网页内容、样式规则,从而改变渲染结果。
  • 布局
    DOM创建之后,渲染引擎将其中的元素对象与样式规则进行结合,可以得到渲染树。布局则是针对渲染树,计算其各个元素的大小、位置等布局信息。
  • 绘图
    使用图形库将布局计算后的渲染树绘制成可视化的图像结果。

总结

本文介绍了浏览器的主要特性以及抽象结构,并选择其中最为核心的渲染引擎进行了介绍。渲染引擎是浏览器中最为复杂的部件,后续将对渲染引擎中的各个模块依次进行介绍。

(完)

参考

  1. Web Browser-Wikipedia
  2. Adam Barth, Collin Jackson, Charles Reis, Google Chrome Team. The Security Architecture of the Chromium Browser.
  3. Andre Campos, Bryan Lane, Neal Clark, Sunpreet Jassal, Stephen Hitchner. Conceptual Architecture of Firefox.
  4. Alan Grosskurth and Michael Godfrey. A case study in architectural analysis: The evolution of the modern web browser.
  5. 主流浏览器内核介绍(前端开发值得了解的浏览器内核历史)
  6. 朱永盛. 《WebKit技术内幕》.
  7. 浏览器的工作原理:新式网络浏览器幕后揭秘
  8. Alan Grosskurth, Michael W.Godfrey. A Reference Architecture for Web Browsers.