Chromium加载网页的过程,需要Browser进程和Render进程协作完成。加载网页的过程由Browser进程发起,向服务器请求网页内容的过程也是由Browser进程完成。Render进程负责对下载回来的网页内容进行解析,解析之后得到一个DOM Tree。有了这个DOM Tree之后,Render进程就可以对网页进行渲染了。本文接下来就对上述过程涉及到的重要概念进行简要介绍以及制定学习计划。

第一个涉及到的重要概念是Chromium的模块划分及其层次关系,如图1所示:

\

图1 Chromium模块划分及其层次关系

这个图来自官方文档:How Chromium Displays Web Pages。从下往上看:

1. WebKit:网页渲染引擎层,定义在命令空间WebCore中。Port部分用来集成平台相关服务,例如资源加载和绘图服务。WebKit是一个平台无关的网页渲染引擎,但是用在具体的平台上时,需要由平台提供一些平台相关的实现,才能让WebKit跑起来。

2. WebKit glue:WebKit嵌入层,用来将WebKit类型转化为Chromium类型,定义在命令空间blink中。Chromium不直接访问WebKit接口,而是通过WebKit glue接口间接访问。WebKit glue的对象命名有一个特点,均是以Web为前缀。

3. Renderer/Renderer host:多进程嵌入层,定义在命令空间content中。其中,Renderer运行在Render进程中,Renderer host运行在Browser进程中。

4. WebContents:允许将一个HTML网页以多进程方式渲染到一个区域中,定义在命令空间content中。

5. Browser:代表一个浏览器窗口,它可以包含多个WebContents。

6. Tab Helpers:附加在WebContents上,用来增加WebContents的功能,例如显示InfoBar。

我们可以将第1层和第2层归结为WebKit层,第3层和第4层归结为Content层,第5层和第6层归结为浏览器层。如果以进程为边界,Tab Helpers、Browser、WebContents和Renderer host运行在Browser进程中,Renderer、WebKit glue和WebKit运行在Render进程中。

Content层是Chromium的核心模块,它实现了Chromium的多进程架构。Content层主要向外提供的接口是WebContents,浏览器层通过这个WebContents接口就可以将一个HTML网页渲染在一个区域上。例如,Chrome就是通过Content层提供的WebContents接口实现一个浏览器的。同样我们也可以通过Content层提供的WebContents接口实现一个与Chrome类似的浏览器,甚至我们也可以通过Content层提供的WebContents接口实现一个嵌入在应用程序的浏览器控件,例如Android 4.4的WebView。

在Content层中,一个用来渲染网页的区域称为RenderView。一个RenderView也称为一个RenderWidget。RenderView与RenderWidget的区别是,前者是描述的是一个用来显示网页内容的控件,后者描述的是一个可以接收用户输入的控件,但是它不一定是用来显示网页内容的。例如,点击网页上的选择框弹出来的窗口,是一个RenderWidget,它里面显示的内容与网页无关。

我们可以将RenderView和RenderWidget看作是一个接口。Browser进程和Render进程都需要实现这个接口。其中,Browser进程分别实现RenderView和RenderWidget接口的两个类是RenderViewHostImpl和RenderWidgetHostImpl,Render进程分别实现RenderView和RenderWidget接口的两个类是RenderViewImpl和RenderWidgetImpl。Browser进程的每一个RenderViewHostImpl对象和每一个RenderWidgetHostImpl对象在Render进程中都分别对应有一个RenderViewImpl对象和一个RenderWidgetImpl。RenderViewHostImpl对象与RenderViewImpl对象、RenderWidgetHostImpl对象与RenderWidgetImpl对象可以通过Browser进程与Render进程建立的IPC通道进行通信。

WebKit层的WebView和WebWidget相当于Content层的RenderView和RenderWidget。我们注意到,WebKit层还有一个称为WebFrame的对象。事实上,Content层也有一个类似的对象,称为RenderFrame。WebFrame和RenderFrame都是用来描述网页的。既然已经有了RenderView和RenderWidget,为什么还需要WebFrame和RenderFrame呢?这与Chromium的Out-of-Process iframes(OOPIFs)项目有关。关于Chromium的Out-of-Process iframes(OOPIFs)项目的详细信息,可以参考官方文档:Out-of-Process iframes (OOPIFs)。

当网页使用window.open在另外一个Tab打开一个新的网页,或者通过iframe标签嵌入另外一个网页时,源网页和目标网页有可能在同一个Render进程中,也有可能在不同的Render进程中,这取决于它们是否来自同一个站点。在HTML5规范中,源网页和目标网页组成了一个浏览上下文单元(Browsing Context)。当源网页和目标网页不在同一个Render进程时,源网页如何通过HTML5规范中的window.postMessage接口发消息给目标网页呢?如图2所示:

\

图2 HTML5的window.postMessage实现

在图2中,网页A通过window.open打开了网页B,它们分别在两个不同的Tab中,这两个Tab又是在不同的Render进程中。在Browser进程中,网页A和网页B分别对应有一个WebContents对象。也就是Browser进程会为每一个网页创建一个WebContents对象,如前面的图1所示。为了让网页A能够通过window.postMessage接口给网页B发送消息,负责渲染网页A的Render进程会为网页B创建一个代理对象,这个代理对象知道如何发送消息给网页B(通过Chromium的IPC消息发送、接收和分发机制分析一文分析的Routing机制)。同样,负责渲染网页B的Render进程也会为网页A创建一个代理以象,这个代理对象负责接收从网页A发送过来的消息,并且分发给网页B处理。注意,代理对象在图2中均通过虚线框表示。通过这种代理对象方式,就实现了不在同一个Render进程中的两个网页的相互通信。

Chromium是如何实现上述代理对象的呢?我们通过图3所示的例子进行说明,如下所示:

\

图3 在同一个Browsing Context中的网页

网页A在一个Tab显示,并且它通过iframe标签包含了网页B和网页C。网页C通过window.open在另外一个Tab中打开了另外一个网页C实例。新打网页的网页C通过iframe标签包含了网页D,网页D又通过iframe标签包含了网页A的另外一个实例。

这时候Browser进程会分别为图3的两个Tab创建一个WebContents对象,如图4所示:

\

图4 RenderFrameHost/RenderFrameProxyHost

每一个WebContents对象都关联有一个Frame Tree。Frame Tree中的每一个Node代表一个网页。第一个Tab的Frame Tree包含有三个Node,分别代表网页A、B和C。第二个Tab的Frame Tree也包含有三Node,分别代表网页C、D和A。

代表网页B的Node关联有一个RenderFrameHost对象和三个RenderFrameProxyHost对象,其中,RenderFrameHost对象描述的是网页B本身,另外三个RenderFrameProxyHosts对象描述的是网页A、C和D。也就是说,在Browser进程中,代理对象是通过RenderFrameProxyHost类描述的。

图3所示的网页A、B、C和D分别在不同的Render进程中渲染,如图5所示:

\

图5 RenderFrame/RenderRenderFrameProxy

在负责渲染网页A的Render进程中,有两个RenderFrame对象,分别代表图3所示的两个网页A实例。负责渲染网页A的Render进程还包含有四个RenderFrameProxy对象,分别代表网页B、C和D。在负责渲染网页B、C和D的Render进程中,也有类似的RenderFrame对象和RenderFrameProxy对象。其中,RenderFrameProxy对象就是前面描述的代理对象。

每一个RenderFrame对象和RenderFrameProxy对象在图1所示的WebKit glue层中,分别对应有一个WebLocalFrame对象和WebRemoteFrame对象,如图6所示:

\

图6 WebLocalFrame/WebRemoteFrame

注意,WebLocalFrame类和WebRemoteFrame类都是从图1的所示的WebFrame类继承下来的,它们都是属于WebKit glue层的。前面我们提到,WebKit glue层是用来封装WebKit层的,WebLocalFrame对象和WebRemoteFrame对象封装的便是WebKit层中的LocalFrame和RemoteFrame对象。Chromium将WebKit glue层和WebKit层统称为Blink模块。这意味着在Blink模块中,前面描述的代理对象是通过WebRemoteFrame和RemoteFrame描述的。

从前面的分析我们就可以看到,在Chromium中,为什么一个网页既要使用RenderView、RenderWidget,又要使用RenderFrame、WebFrame来描述,它们的作用是不一样的,总结来说,就是:

1. RenderView描述的是一个用来显示网页内容的RenderWidget。

2. RenderWidget描述的是一个UI控件。

3. RenderFrame用来建立网页之间的消息通道。

在WebKit层中,每一个LocalFrame对象都关联有一个LocalDOMWindow对象,这个LocalDOMWindow对象又关联有一个Document对象。这个Document对象描述的就是一个要在当前Render进程进行加载和渲染的网页。

在WebKit层中,每一个RemoteFrame对象都关联有一个RemoteDOMWindow对象。但是由于RemoteFrame对象描述的是一个代理对象,因此它关联的RemoteDOMWindow对象是不关联有Document对象的,只是作为一个Place Holder存在当前Render进程中存在。

LocalDOMWindow对象和Document对象描述的就是HTML规范的DOM Window和Document,它们是在网页的加载和解析过程中创建的。其中,Document对象包含有一个DOM Tree,如图7所示:

\

图7 DOM Tree和Layer Tree

这个图来自官方文档:GPU Accelerated Compositing in Chrome。DOM Tree中的每一个Node对应的就是网页中的每一个HTML标签。每一个HTML标签都对应有一个Render Object,这些Render Object又形成一个Render Object Tree。Render Object知道如何绘制其描述的HTML标签。

具有相同坐标空间的Render Object都绘制在同一个Render Layer中,这些Render Layer又形成了一个Render Layer Tree,这意味着并不是所有的Render Object都有自己Render Layer。Render Layer Tree的根节点一定对应有一个Render Layer,其余的子节点如果不需要使用的单独的Render Layer,那么就会与父节点使用相同的Render Layer。因此,Render Object与Render Layer是多对一的关系。典型地,设置有透明属性、CSS Filter的Render Object有单独的Render Layer,标签canvas和video对应的Render Object也有单独的Render Layer。Layer是图形渲染引擎普遍使用的一个技术,是为了方便绘制一组具有某些相同属性的图形而生的,这样就不会为每一个图形都单独执行相同的绘图操作。

在图形渲染引擎中,Layer会对应有一个Backing Surface。在软件方式渲染中,Backing Surface就是一个内存Buffer。在硬件方式渲染中,Backing Surface就是一个FBO。为了减少Buffer和FBO开销。WebKit不会为每一个Render Layer都分配一个Backing Surface,而是让某些Render Layer共用同一个Backing Surface。这意味着Render Layer与Backing Surface是多对一的关系。在WebKit中,具有Backing Surface的Layer称为Graphics Layer,这些Graphics Layer又形成了一个Graphics Layer Tree。每一个Graphics Layer都关联有一个Graphics Context。这个Graphics Context是由Chromium提供给WebKit的,它知识如何绘制Render Layer的内容。Graphics Context绘制出来的内容最后会通过合成器(Compositor)渲染在屏幕上。

上面描述的Render Object Tree、Render Layer Tree和Graphics Layer都是与网页渲染相关的,是我们下一个系列的文章要分析的内容。在这个系列的文章中,我们主要是分析DOM Tree以及前面描述的Frame Tree。

Frame Tree由Browser进程创建,DOM Tree由Render进程创建。Frame Tree是在网页内容下载回来前就创建出来的,并且在后面网页的解析和导航时增加或者移除子节点。DOM Tree是在网页内容下载回来后进行创建的,并且是根据网页的内容进行创建的。当一个网页的DOM Tree创建出来之后,它的加载过程就完成了。

注意,网页内容下载是由Browser进程执行的。Browser进程再将下载回来的网页通过共享内存交给Render进程处理。为什么不直接由Render进程下载呢?这是因为为了安全起见,Render进程按照最小权限原则创建,它不具有网络访问权限,因此就不能从服务器上下载网页内容回来。

为了更好地理解网页加载过程,以及这个过程中涉及到的各种对象,接下来我们将按照以下三个情景分析网页的加载过程:

1. Frame Tree的创建过程;

2. 网页下载过程;

3. DOM Tree的创建过程。

将网页抽象为DOM Tree之后,WebKit后面就可以对它进行绘制了。网页的绘制是我们下一个系列文章的关注点,同时也是浏览器的核心所在,因为评价一个浏览器是否流畅就取决于它绘制网页的速度够不够快。DOM Tree是网页进行绘制的起点,因此敬请关注这个系列的文章!

https://www.2cto.com/kf/201601/456010.html

Chromium网页加载过程相关推荐

  1. 关于前端性能优化问题,认识网页加载过程和防抖节流

    前端性能优化-网页加载过程.性能优化方法.防抖和节流 一.网页加载过程 1.加载资源的形式 2.加载资源的过程 3.渲染页面的过程 4.关于window.onload 和 DOMContentLoad ...

  2. linux优化网页加载过程,HTML页面加载和解析流程 介绍

    1.浏览器加载和渲染html的顺序 1.1.IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的. 1.2.在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相 ...

  3. linux优化网页加载过程,【zz】Linux起步过程中硬件模块的加载

    [zz]Linux起步过程中硬件模块的加载 [zz]Linux起步过程中硬件模块的加载 日期:2014-05-16 浏览次数:20354 次 [zz]Linux启动过程中硬件模块的加载 文章来源不详. ...

  4. webrender 查看是否开启_想要体验极致顺滑的网页加载体验?手动开启Firefox WebRender渲染引擎...

    昨天我们提到火狐浏览器最新稳定版Mozilla Firefox v67 版将面向部分用户开启WebRender渲染引擎测试. 据火狐浏览器团队介绍当用户开启新的渲染引擎后 ,  网页加载帧率能够从现有 ...

  5. 页面加载过程(url->页面)

    当我们在浏览器输入URL地址开始,到web页面加载完毕,这个过程称作网页加载过程.具体如下: 在浏览器地址栏输入URL DNS域名解析 发送HTTP请求 服务器接收请求做出响应 浏览器解析渲染页面 1 ...

  6. chromium 调试之inspect--调试网页数据资源加载过程

    我们知道漂亮的网页时有多种多媒体元素组成的,我们在开发/调试浏览器引擎过程中有可能会遇到网页加载过慢/网页显示不全/进度条走的太慢等各类问题,chrome本省包含的inspect工具可以帮助我们详细的 ...

  7. 移动网站性能优化:网页加载技术概览

    移动网站性能优化:网页加载技术概览 2013/08/27 | 分类: IT技术 | 0 条评论 | 标签: WEB开发, 性能优化, 移动 分享到: 47 本文由 伯乐在线 - 伯乐在线读者 翻译自  ...

  8. Chrome现在也能编辑pdf文件了!64位安卓版上线,网页加载快10%,还有良心标签管理功能...

    贾浩楠 发自 凹非寺 量子位 报道 | 公众号 QbitAI 全世界最多人在用的Chrome浏览器,今天更新了. 版本号:Chrome 85. 增加一系列标签管理功能,还自带PDF编辑器,并且提升10 ...

  9. 内容分发网络 CDN 是如何提高网页加载时间的?

    几乎 Internet 上的每个人都体验过内容分发网络 (CDN) 的好处.大多数科技公司,包括谷歌.苹果和微软等公司,都使用 CDN 来减少加载网页内容的延迟. CDN 通常会将服务器放置在不同网络 ...

最新文章

  1. Go对Python产生的冲击
  2. 分布式深度学习最佳入门(踩坑)指南
  3. cesium 经纬度绘制点_cesium结合geoserver利用WFS服务实现图层新增(附源码下载)
  4. zabbix 3.2.2 server端(源码包)安装部署 (一)【转】
  5. iOS 关于枚举的使用
  6. linux 进sqlplus命令,linux下的sqlplus命令
  7. 看完这篇文章,会让你对电容的作用更明白!
  8. python设计模式15-解释器模式
  9. (27)呼吸灯verilog与VHDL编码(学无止境)
  10. EOS Nation更新“flash.sx遭攻击”进展:将建议MSIG根据快照将资金退还
  11. 首套房贷款首付多少?
  12. Linux之watch命令
  13. 再谈UDP协议—浅入理解深度记忆
  14. bagging boosting 随机森林 GBDT对比
  15. 《计算机操作系统》第四版(汤小丹考研版) 全书知识梳理
  16. json html api文档,jsonEditor api介绍
  17. python计算学分绩点的程序_Python爬虫实战七之计算大学本学期绩点
  18. java GUI程序的编写入门
  19. win10未启动对远程服务器启动,win10系统连接远程提示未启用对服务器的远程访问的操作技巧...
  20. 带你了解2021世界人工智能大会上的AI新趋势

热门文章

  1. canvas--如何实现H5移动端电子签名
  2. 台达ES2与台达温控器ASCII通讯程序 可以实现温控器运行,停止。 目标值设定,警报上下限的设定
  3. 结构张量structure tensor(matlab)
  4. 第二高的薪水 第N高的薪水
  5. 将html中的style内联样式转换为行内样式
  6. 如何修改计算机设备的登录名称
  7. H265码流分析详解
  8. 子女不得以放弃继承权为由,拒绝赡养老人
  9. 刷题术语简称:OJ、AC、WA、TLE、OLE、MLE、RE、PE、CE分别代表的意思
  10. 吹气压力传感器US6310 US6330调试