Safari和Chrome使用webkit内核进行页面渲染。
webkit引擎渲染流程
浏览器包含3个很重要的进程:浏览器进程,网络进程,渲染进程。
渲染进程会从网络进程请求html文档的内容。
渲染引擎(渲染进程)开始解析HTML文档,构建DOM树,如果遇到了CSS文件,那么会边下载解析CSS,边构建DOM树,待CSS解析完成后,就可以构建渲染树了。也就是说,CSS会阻塞渲染树的构建,而不会阻塞DOM树的构建。
当CSS在解析过程中,会禁止js脚本的执行。原因是,脚本在文档解析阶段会请求样式信息,如果当时还没有解析完CSS,就去执行脚本,脚本就会得到错误的结果。
在HTML文档的解析过程中,遇到js脚本时,会阻塞HTML文档的解析,然后下载js脚本,当CSS解析完成后,立即执行js脚本。当js脚本下载执行完毕后在继续解析HTML。
当遇到图片文件时,会边下载图片,边解析HTML文本,甚至不等图片下载完成,就进行页面渲染。
为了达到更好的用户体验,渲染引擎会力求尽快将内容显示在屏幕上,它不必等到整个HTML文档解析完毕后,就会构建渲染树,设置布局并渲染页面,在不断接收和处理来自网络的其余内容的同时,渲染引擎会将部分内容解析并显示出来。

html解析流程例子
- 用户输入网址(假设是个html页面,并且是第一次访问),浏览器向服务器发出请求,服务器返回html文件;
- 浏览器开始载入html代码,发现<head>标签内有一个<link>标签引用外部CSS文件;
- 浏览器又发出CSS文件的请求,服务器返回这个CSS文件;
- 浏览器继续载入html中<body>部分的代码,并且CSS文件已经拿到手了,可以开始渲染页面了;
- 浏览器在代码中发现一个<img>标签引用了一张图片,向服务器发出请求。此时浏览器不会等到图片下载完,而是继续解析后面的代码;
- 服务器返回图片文件,由于图片占用了一定面积,影响了后面段落的排布,因此浏览器需要回过头来重新渲染这部分代码;
- 浏览器发现了一个包含一行Javascript代码的<script>标签,赶快运行它;
- Javascript脚本执行了这条语句,它命令浏览器隐藏掉代码中的某个<div> (style.display=”none”)。突然少了这么一个元素,浏览器不得不重新渲染这部分代码;
优化
预解析
在执行脚本时,其他线程会解析文档的其余部分,找出并下载需要通过网络下载的资源,通过这种方式,资源可以在并行连接上下载,从而提高总体速度。预解析不会修改DOM树,而是将这项工作交由主解析器处理。