引子:2008年,Google公司以苹果开源项目WebKit作为内核,创建了一个新的项目Chromium,该项目的目标是创建一个快速的、支持众多操作系统的浏览器,包括
对桌面操作系统和移动操作系统的支持。WebKit是Chromium浏览器的内核,而Chrome浏览器一般选择Chromium的稳定版本作为它的基础,Chrome加入了一些私有的
编码解码器以支持音视频等,以及整合了Google众多的网络服务。

以下是WebKit和Chromium的关系,那么渲染引擎(浏览器内核)和WebKit是什么关系?

clipboard.png

构建对象模型

浏览器渲染页面前先要构建DOM和CSSOM树,但这个构建过程不会去渲染

  • 字节 → 字符 → 令牌 → 节点 → 对象模型。
  • HTML 标记转换成文档对象模型 (DOM);CSS 标记转换成 CSS 对象模型 (CSSOM)。
  • DOM 和 CSSOM 是独立的数据结构。
  • Chrome DevTools Timeline 让我们可以捕获和检查 DOM 和 CSSOM 的构建和处理开销

 

浏览器每次处理 HTML 标记时,都会完成以上所有步骤:将字节转换成字符,确定令牌,将令牌转换成dom节点,然后构建 DOM 树。这整个流程可能需要一些时间才能完成,有大量 HTML 需要处理时更是如此。

在浏览器构建我们这个简单页面的 DOM 时,在文档的 head 部分遇到了一个 link 标记,该标记引用一个外部 CSS 样式表:style.css。由于预见到需要利用该资源来渲染页面,它会立即发出对该资源的请求,如果不另外声明,会是阻塞后面渲染的资源请求

 

CSSOM 为何具有树结构?为页面上的任何对象计算最后一组样式时,浏览器都会先从适用于该节点的最通用规则开始(例如,如果该节点是 body 元素的子项,则应用所有 body 样式),然后通过应用更具体的规则(即规则“向下级联”)以递归方式优化计算的样式。不过要记得浏览器有自己的默认样式,因此一开始以此为基础建立cssom树,我们平时用reset来覆盖和重新计算样式。

CSSOM和DOM是独立的数据结构,浏览器将两者关联在一起生成渲染树

渲染引擎及网页渲染

为用户提供网页浏览服务无疑是最重要的功能,如下介绍:

渲染引擎

  • 渲染引擎- 能够能够将HTML/CSS/JavaScript文本及相应的资源文件转换成图像结果.
  • 作用- 将资源文件转化为用户可见的结果。
  • 渲染引擎的种类 -Tridend(IE)、Gecko(FF),WebKit(Safari,Chrome,Andriod浏览器)等.
  • 介绍-WebKit是由苹果2005年发起的一个开源项目,引起了众多公司的重视,几年间被很多公司所采用,在移动端更占据了垄断地位。更有甚者,开发出了基于WebKit的支持HTML5的web操作系统(如:Chrome OS、Web OS)。

WebKit的大致结构

VAmvu9.md.png

介绍:

  • 图中的实线框,虚线框代表什么:

    • 实线框- 模块是所有移植的共有部分
    • 虚线框- 不同的厂商可以自己实现
  • 操作系统- 是管理控制计算机硬件软件资源计算机程序,是直接运行在“裸机”上的最基本的系统软件任何其他软件都必须在操作系统的支持下才能运行WebKit也是在操作系统上工作的
  • 第三方库- 为了WebKit提供支持,如图形库、网络库、视频库等。
  • WebCore- 是各个浏览器使用的共享部分,包括HTML解析器、CSS解析器、DOM和SVG等。

    • JavaScriptCore- 是WebKit的默认引擎,在谷歌系列产品中被替换为V8引擎。
    • WebKit Ports- 是WebKit中的非共享部分,由于平台差异第三方库需求的不同等原因,不同的移植导致了WebKit不同版本行为不一致,它是不同浏览器性能和功能差异的关键部分。
  • WebKit嵌入式编程接口 -供浏览器调用\`,与移植密切相关,不同的移植有不同的接口规范。
  • 测试用例,包括布局测试用例和性能测试用例,用来验证渲染结果的正确性。

网页渲染流程

上面介绍了渲染引擎的各个模块,那么一张网页,要经历怎样的过程,才能展示给用户。

VAuPZn.png

过程- 首先是网页内容,输入到HTML解析器,HTML解析器解析,然后构建DOM树,在这期间如果遇到JavaScript代码则交给JavaScript引擎处理;如果来自CSS解析器的样式信息,构建一个内部绘图模型。该模型由布局模块计算模型内部各个元素的位置和大小信息,最后由绘图模块完成从该模型到图像的绘制。在网页渲染的过程中,大致可分为下面3个阶段:

  • 1.从输入URL到生成DOM树

    • 1.1 地址栏输入URL,WebKit调用资源加载器加载相应资源;
    • 1.2 加载器依赖网络模块建立连接,发送请求并接收答复;
    • 1.3 WebKit接收各种网页或者资源数据,其中某些资源可能同步或异步获取;
    • 1.4 网页交给HTML解析器转变为词语
    • 1.5 解释器根据词语构建节点,形成DOM树;
    • 1.6 如果节点是JavaScript代码调用JavaScript引擎解释并执行
    • 1.7 JavaScript代码可能会修改DOM树结构;
    • 1.8 如果节点依赖其他资源,如图片\css、视频等,调用资源加载器加载它们,但这些是异步加载的,不会阻碍当前DOM树继续创建;如果是JavaScript资源URL(没有标记异步方式),则需要停止当前DOM树创建,直到JavaScript加载并被JavaScript引擎执行后才继续DOM树的创建
  • 2.从DOM树到构建WebKit绘图上下文

    • 2.1 CSS文件被CSS解释器解释成内部表示;
    • 2.2 CSS解释器完成工作后,在DOM树上附加样式信息,生成RenderObject树;
    • 2.3 RenderObject节点在创建的同时,WebKit会根据网页层次结构构建RenderLayer树,同时构建一个虚拟绘图上下文
  • 3.绘图上下文到最终图像呈现

    • 3.1 绘图上下文是一个与平台无关的抽象类,它将每个绘图操作桥接到不同的具体实现类,也就是绘图具体实现类;
    • 3.2 绘图实现类也可能有简单的实现,也可能有复杂的实现,软件渲染、硬件渲染、合成渲染等;
    • 3.3 绘图实现类将2D图形库或者3D图形库绘制结果保存,交给浏览器界面进行展示。

上述是一个完整的渲染过程,现代网页很多都是动态的,随着网页与用户的交互,浏览器需要不断的重复渲染过程。

JavaScript引擎

VAK30s.png

JavaScript本质上是一种解释型语言,与编译型语言不同的是它需要一遍执行一边解析,而编译型语言在执行时已经完成编译,可直接执行,有更快的执行速度(如上图所示)。JavaScript代码是在浏览器端解析和执行的,如果需要时间太长,会影响用户体验。那么提高JavaScript的解析速度就是当务之急。JavaScript引擎和渲染引擎的关系如下图所示:

VAKBnJ.png

JavaScript语言是解释型语言,为了提高性能引入Java虚拟机C++编译器中的众多技术。现在JavaScript引擎的执行过程大致是:

源代码-→抽象语法树-→字节码-→JIT-→本地代码(V8引擎没有中间字节码)。一段代码的抽象语法树示例如下:

function demo(name) {
    console.log(name);
}

抽象语法树如下:

VAKTAI.png
V8更加直接的将抽象语法树通过JIT技术转换成本地代码,放弃了在字节码阶段可以进行的一些性能优化,但保证了执行速度。在V8生成本地代码后,也会通过Profiler采集一些信息,来优化本地代码。虽然,少了生成字节码这一阶段的性能优化,但极大减少了转换时间。

但是在2017年4月底,v8 的 5.9 版本发布了,新增了一个 Ignition 字节码解释器,将默认启动,从此之后将与JSCore有大致相同的流程。做出这一改变的原因为:(主要动机)减轻机器码占用的内存空间,即牺牲时间换空间;提高代码的启动速度;对 v8 的代码进行重构,降低 v8 的代码复杂度(V8 Ignition:JS 引擎与字节码的不解之缘 - CNode技术社区)。

JavaScript的性能和C相比还有不小的距离,可预见的未来估计也只能接近它,而不是与它相比,这从语言类型上已经决定。下面将对V8引擎进行更为细致的介绍。

参考

WebKit技术内幕


白鲸鱼
1k 声望110 粉丝

方寸湛蓝