webkit 渲染机制
最近看了< webkit技术内幕 >,虽然并不能完全看懂,但是对浏览器的渲染机制也算是有了一个比较完整的认识。
我们从浏览器地址栏输入网址开始到web页面被完整的呈现在眼前,大概的经过了这样一个过程:网址被DNS解析为IP地址 -> 通过IP地址建立TCP连接 -> 发送HTTP请求 -> 服务器处理请求并返回响应 -> 浏览器解析渲染页面 -> 断开TCP连接
可是浏览器是怎么去解析渲染页面的呢?这里就要了解浏览器的内核,也就是浏览器的渲染引擎(严格来说应该是渲染引擎 + Javascript引擎),页面的渲染工作便是由渲染引擎完成的。需要注意浏览器和浏览器内核是不同的概念,浏览器指的是 Chrome、Firefox 等,而浏览器内核则是 Blink、Gecko 等,浏览器内核只负责渲染,GUI 及网络连接等跨平台工作则是浏览器实现的。主流的渲染引擎包括Trident、Gecko、Webkit,它们分别是IE、火狐和Chrome的内核(2013年,Google宣布了Blink内核,它其实是从Webkit复制出去的)。一般渲染引擎主要包括HTML解释器、CSS解释器、Javascript引擎、布局、绘图等模块。当然这些模块还依赖很多其他的基础模块。
我们先简单的了解一下渲染引擎各个主模块所做的工作(以下所有的介绍以 webkit 为介绍对象)
HTML解释器 :HTML解释器的工作就是将网络或者本地磁盘获取到的HTML网页和资源从字节流解释成DOM树的结构(首先是字节流,经过解码之后是字符流,然后通过词法分析器会被解释成词语(TOKENS),经过语法分析器构建成节点,最后这些节点被组建成一颗DOM树)
CSS解释器 :CSS字符串被CSS解释器处理后变成渲染引擎的内部规则表示。(样式规则建立完成之后,webkit会保存规则结果,当DOM的节点建立之后,webkit会为可视化节点选择合适的样式信息,即作样式规则匹配)
Javascript引擎 :将Javascript代码处理并执行,一个Javascript引擎可以包括以下几个部分 ->
编译器 -> 主要工作是将源代码编译成抽象语法树,在某些引擎中还包括将抽象语法树转换为字节码(JavascriptCore 引擎)。
解释器 -> 在某些引擎中,解释器主要是接收字节码,解释执行字节码,同时也依赖垃圾回收机制等。
JIT工具 -> 将字节码或者抽象语法树转换为本地代码 (V8 引擎)
垃圾回收器和分析工具
布局 :计算RenderObject对象的位置、大小等信息
绘图 :将构建好的渲染内部表示模型使用图形库绘制出来
页面的最终渲染便是上述模块综合处理的结果。根据数据的流向,这里可以把渲染的过程分为三个阶段,第一个阶段是从网页的url到构建完dom树,第二个阶段是从dom树到构建完webkit的绘图上下文,第三个阶段是从绘图上下文到生成最后的图像。

上图描述的是网页 url 到构建完DOM树的整个过程,数字表示的是基本顺序,不过也不是严格一致,因为这个过程可能会有所重复或者交叉。
具体的过程如下:
1 当用户输入网页url的时候,webkit调用资源加载器加载对应的网页。
2 加载器依赖网络模块建立连接,发生请求并接收响应。
3 webkit接收到各种网页或者资源的数据,其中某些资源可能是同步或者异步的方式获取的。
4 网页被交给HTML解释器解释成一系列词语(Token)
5 解释器根据词语构建节点(Node),形成DOM树。
6 如果节点是Javascript代码的话,调用Javascript引擎解释执行。
7 Javascript代码可能会修改DOM树的结构。
8 如果有节点需要依赖其他的资源,比如图片、css、视频等,调用资源加载器来加载它们,不过这个过程是异步的,不会阻碍当前DOM树的继续构建。如果是Javascript资源 url (没有标记异步方式),则需要停止当前DOM树的构建,直到Javascript的资源被加载并被Javascript引擎解释执行后才继续DOM树的创建。
在上述过程当中,网页在加载和被渲染完毕的这一段过程会相继发出“DOMContent”事件和“onload”事件,分别表示DOM树构建完毕以及DOM树及其所有依赖的资源都加载完毕。一般来说“DOMContent”事件会先于“onload”事件发生。
接下来就是Webkit借助 css 和 dom 树构建RenderObject树直到绘图上下文。
1 css文件被css解释器解释为内部表示结果
2 css解释器完成工作之后在dom树上附加解释后的样式信息,这就是RenderObject树
3 RenderObject节点被创建的同时,webkit会根据网页的层次结构创建RenderLayer树,同时创建一个虚拟的绘图上下文。
RenderObject树的建立并不会导致DOM树被销毁,上述四个内部表示结构直到网页被销毁都一直存在。
最后就是根据绘图上下文来生成最终图像了,这一过程主要依赖2D和3D图形库。
生成过程的简单描述如下图所示:

整个渲染的流程至此便是结束了,从渲染的整个过程中我们也可以发现,原来 CSS、图片、视频等资源的加载是异步的,同 dom 树的构建是并发的,而 Javascript 资源的加载和执行却是同步的,这个过程会阻塞 dom 树的构建,同时当然也会阻碍后续资源(比如图片资源)的下载,因为这时候webkit对需要什么资源一无所知,这导致了资源不能并发下载这一严重的性能问题。(其实对于这样的情况,webkit采取了资源预扫描和预加载的机制来实现资源的并发下载而不被 Javascript 的执行所阻碍,但仍要避免这种情况的出现,因为并不是所有的渲染引擎都做了如此的考虑)。所以从这里我们也可以得到一些关于渲染优化方面的启示:
1 最好把脚本文件放在HTML文件的末尾,这样就不会阻塞 dom 树的构建和资源的并发下载
2 如果非要把脚本文件放在HTML文件的前面,请给 script 标签添加 “async” 属性或者 “defer” 属性。前者表明这是一段可以异步执行的 Javascript 代码,而后者表示在加载完 Javascript 之后延迟到 dom 树构建就绪之后再执行代码。如果同时添加 “async” 和 “defer” ,在同时支持这两个属性的浏览器中 “async” 会覆盖掉 “defer”。需要注意的一点是,如果当前添加 “async” 属性的脚本文件依赖有其他的脚本文件,可能会导致添加 “async” 属性的脚本文件先于依赖脚本执行,即使依赖脚本先于添加 “async” 属性的脚本文件被定义。
webkit 渲染机制的更多相关文章
- 2013 QCon北京演讲:跨终端的WebKit渲染机制
转载请注明原文地址:http://blog.csdn.net/milado_nju 1. 该演讲主要介绍WebKit的渲染机制的内部工作原理和一些新的技术,特别是针对不断出现的多种终端所做的一些努力. ...
- 理解WebKit和Chromium: Chromium WebView和Chrome浏览器渲染机制
转载请注明原文地址:http://blog.csdn.net/milado_nju ## 数据对比 前面介绍过Chromium WebView的时候,说过有关ChromiumWebView同Chrom ...
- JS学习笔记:(一)浏览器页面渲染机制
浏览器的内核主要分为渲染引擎和JS引擎.目前市面上常见的浏览器内核可以分为这四种:Trident(IE).Gecko(火狐).Blink(Chrome.Opera).Webkit(Safari).这里 ...
- WebKit 渲染过程
webkit笔记,主要来自 朱永盛 <WebKit技术内幕> 学习笔记,转载就注明原著,该书是国内仅有的Webkit内核的书籍,学习的好导师,推荐有兴趣的朋友可以购买 Webkit渲染过程 ...
- [转]浏览器渲染机制——一定要放在body底部的js引用
转自:http://blog.csdn.net/u012251421/article/details/50536265 说明: 本文提到的浏览器均是指Chrome. “script标签“指的都是普通的 ...
- Android渲染机制和丢帧分析
http://blog.csdn.net/bd_zengxinxin/article/details/52525781 自己编写App的时候,有时会感觉界面卡顿,尤其是自定义View的时候,大多数是因 ...
- Vue项目预渲染机制引入实践
周末想顺便把已经做好静态页面的webApp项目做一下SEO优化,由于不想写蹩脚的SSR代码,所以准备采用预渲染,本来想着网上有这么多预渲染的文章,随便找个来跟着做不就完了嘛,结果年轻的我付出了整个周末 ...
- float浮动-清浮动BFC渲染机制
float浮动,用于横向布局. 起初的横向布局都用display:inline-block,但是这会导致两个元素之间有空隙,而这是由代码换行解析成空格的,解决元素间有空隙,空格:font-size:0 ...
- 转---JS 一定要放在 Body 的最底部么?聊聊浏览器的渲染机制
作者:德来 segmentfault.com/a/1190000004292479 如有好文章投稿,请点击 → 这里了解详情 一.从一个面试题说起 面试前端的时候我喜欢问一些看上去是常识的问题.比如: ...
随机推荐
- lPC1788的GPIO驱动
#include "led.h" void led_init(void) { //p1.14 p0.16 p1.13 p4.27 LPC_SC->PCONP |= (1< ...
- tp框架 使用ajax
<head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8&quo ...
- Maven项目中pom文件分析
pom英文全称: project object model 1.概述 pom.xml文件描述了maven项目的基本信息,比如groupId,artifactId,version等.也可以对maven项 ...
- [Angular Tutorial] 6-Two-way Data Binding
在这一步中,您将会添加一个新特性来使得您的用户可以控制电话列表中电话的顺序,动态改变顺序是由创建一个新的数据模型的特性实现的,将它和迭代器绑定在一起,并且让数据绑定神奇地处理下面的工作. ·除了搜索框 ...
- reg 正则
//转化为camel形式 var text = 'border-color-base'; text.replace(/-(\w{1})/g, function (match, chr1) { retu ...
- 简单的shared_ptr实现
RT,代码参考了STL中shard_ptr的实现,基本原理是引用计数,利用Ref_cnt类来管理内存,在shared_ptr创建时创建,此后shared_ptr仅是在拷贝复制析构的过程中对引用进行修改 ...
- @dynamic、@synthesize
声明property属性后,有2种实现选择: @synthesize 编译器期间,让编译器自动生成getter/setter方法. 当有自定义的存或取方法时,自定义会屏蔽自动生成该方法 @dynami ...
- PHPCMS 详情页静态化
<?php defined('IN_PHPCMS') or exit('No permission resources.'); pc_base::load_app_class('admin',' ...
- Unity3D在NGUI中使用mask
过程是这样的:最近一直想做一个头像的mask效果,后来发现原来unity的mask需要用shader来写,网上找了不少资料,也能实现,不过大多数都是用render texture作为相机投影的text ...
- JAVA中StringBuffer类常用方法
String是不变类,用String修改字符串会新建一个String对象,如果频繁的修改,将会产生很多的String对象,开销很大.因此java提供了一个StringBuffer类,这个类在修改字符串 ...