这里我们以WebKit为主进行分析,其他浏览器内核基本与此相同
浏览器
浏览器我们都知道,就是在输入一个URL后,将URL变化成一个可视化,可操作的页面。在这个过程中,浏览器到底都有哪些模块,怎样完成这样一个效果的呢?
我们按照浏览器数据流的流向,可以将上述这个过程分成三个阶段。
- 从网页的URL到构建完DOM树。
- 从DOM树到构建完绘制上下文。
- 第三个阶段是从绘制上下文到生成最终的图像。
从网页的URL到构建完DOM树
- 用户输入URL后,调用资源类加载器加载改URL对应的网页。
- 加载器依赖网络模块建立连接,发送请求并接受应答。
- 接受到各种网页或者资源数据,这些资源有可能是同步的,又有可能是异步的。
- 网页被交给HTML解析器变成一系列的词语(Token)
- 解析器根据词语构建节点,形成DOM树。
- 如果节点是JavaScript代码,调用JavaScript引擎并执行。
- JavaScriptdiam可能会修改DOM树的结构。
- 如果节点需要依赖其他资源,如图片,CSS,视频等,调用资源加载器来加载它们。但是它们是异步的。不会阻塞当前DOM树的继续创建;如果是JavaScript资源URL(没有标记 async活defer)。则需要停止当前DOM树的创建,直到JavaScript的资源加载并被JavaScript引擎执行后才继续DOM树的创建。
在上面这个过程中,有个非常重要的一点就是DOMConent事件和DOM的“onload”事件。这两事件分布发生在DOM树构建完之后,以及DOM树构建完,并且网页所依赖的资源都加载完之后才发生。完成上的系列操作后,接下来就是利用CSS和DOM树构架RenderObject树再到绘制上下文。
从DOM树到构建完绘制上下文
- CSS文件被CSS解释器解释成内部表示结构
- CSS解释器工作完成之后,在DOM树上附加解释后的样式信息,这既是RenderObject树。
- RenderObject节点在创建的同时,WebKit会根据网页的层次构建RenderLayer树,同时构建一个虚拟的绘图上下文。
从绘制上下文到生成最终的图像
构建为绘制上线文后,接下来就是根据绘制上下文生成最终图像了。这个主要依赖2D和3D图形库。如下图:
上面就是浏览器渲染的三个组要阶段。通过上面的分析,我们可以知道在DOM构建的过程中需要执行JavaScriptdiam,所以需要特别注意在DOM未构建完成是,不能访问DOM,对DOM进行操作。
关于页面的布局及计算参考: 布局计算
渲染
渲染其实是从绘制上下文到最终图像中的一部分,这儿提出来的主要原因是,后面的动画优化会有用。
每个RenderLayer对象可以看做为一个图层。最终图像就是由各个不同的RenderLayer合成(Compositing)的。
关键路径
根据上对浏览器渲染过程的了解,可以将浏览器渲染过程总结为以下关键路径,如下图:
- 请求网资源。
- 处理HTML标记并构建DOM树。
- 处理CSS标记并构建CSSOM树。
- 将DOM与CSSOM合并为渲染树RenderTree。
- 根据渲染树进行渲染。
- 合成最终图像呈现到用户界面。
上面过程我们把它可以叫做关键渲染路径,虽然实际工作中,这个过程要比这负责的多。如DOM 或 CSSOM 被修改,只能再执行一遍以上的某些有步骤,以确定需要加载那些新资源,那些像素需要在屏幕上进行重新渲染。但是我们了解了这个关键路径后,就可以对其做优化,这样就可以达到尽快的将内容渲染到屏幕上,用来缩短首次渲染屏幕刷新的时间,提供更好的用户体验。
在步骤5中包含了一下三个小的步骤。需要特别注意一下:
- 布局计算并且生成RenderLayer。
- 绘图生成渲染图像。
- 合成最终图像。
步骤1将会生成不同的RenderLayer,我们可以把这个过程叫做Layout。
步骤2将会使用图形库绘制图像,在这个过程中,WebKit支持两种模式。如果使用CPU绘制,则为软件绘制。如果使用GPU绘制,则成为硬件加速绘制。
步骤3中会将不同的图层合成到一起生成最终的图像。这种使用合成技术的渲染称为合成渲染,WebKit就是使用这种技术来完成渲染的。
总结:
通过对浏览器渲染过程和关键路径的了解,我们可以在实际项目中针对性的做出合理的性能优化,从而提升项目质量。