0

0

浏览器解析渲染HTML文档的过程详解(图文)

不言

不言

发布时间:2019-03-26 09:43:16

|

3890人浏览过

|

来源于segmentfault

转载

本篇文章给大家带来的内容是关于浏览器解析渲染HTML文档的过程详解(图文),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

浏览器的工作原理

一、浏览器的高层结构

浏览器的主要组件为:

1、用户界面 - 包括地址栏、前进/后退按钮、书签菜单等。除了浏览器主窗口显示的您请求的页面外,其他显示的各个部分都属于用户界面。

2、浏览器引擎 - 在用户界面和呈现引擎之间传送指令。

3、呈现引擎 - 负责显示请求的内容。如果请求的内容是 HTML,它就负责解析 HTML 和 CSS 内容,并将解析后的内容显示在屏幕上。

4、网络 - 用于网络调用,比如 HTTP 请求。其接口与平台无关,并为所有平台提供底层实现。

5、用户界面后端 - 用于绘制基本的窗口小部件,比如组合框和窗口。其公开了与平台无关的通用接口,而在底层使用操作系统的用户界面方法。

立即学习前端免费学习笔记(深入)”;

6、JavaScript 解释器。用于解析和执行 JavaScript 代码。

7、数据存储。这是持久层。浏览器需要在硬盘上保存各种数据,例如 Cookie。新的 HTML 规范 (HTML5) 定义了“网络数据库”,这是一个完整(但是轻便)的浏览器内数据库。

layers.png

值得注意的是,和大多数浏览器不同,Chrome 浏览器的每个标签页都分别对应一个呈现引擎实例。每个标签页都是一个独立的进程。

二、主流程

呈现引擎一开始会从网络层获取请求文档的内容,内容的大小一般限制在 8000 个块以内。

然后进行如下所示的基本流程:

flow.png

呈现引擎将开始解析 HTML 文档,并将各标记逐个转化成“内容树”上的 DOM 节点。同时也会解析外部 CSS 文件以及样式元素中的样式数据。HTML 中这些带有视觉指令的样式信息将用于创建另一个树结构:呈现树。

呈现树包含多个带有视觉属性(如颜色和尺寸)的矩形。这些矩形的排列顺序就是它们将在屏幕上显示的顺序。

呈现树构建完毕之后,进入“布局”处理阶段,也就是为每个节点分配一个应出现在屏幕上的确切坐标。下一个阶段是绘制 - 呈现引擎会遍历呈现树,由用户界面后端层将每个节点绘制出来。

需要着重指出的是,这是一个渐进的过程。为达到更好的用户体验,呈现引擎会力求尽快将内容显示在屏幕上。它不必等到整个 HTML 文档解析完毕之后,就会开始构建呈现树和设置布局。在不断接收和处理来自网络的其余内容的同时,呈现引擎会将部分内容解析并显示出来。

主流程示例:

webkitflow.png

三、处理脚本和样式表的顺序

1、脚本

网络的模型是同步的。网页作者希望解析器遇到

2、预解析

WebKit 和 Firefox 都进行了这项优化。在执行脚本时,其他线程会解析文档的其余部分,找出并加载需要通过网络加载的其他资源。通过这种方式,资源可以在并行连接上加载,从而提高总体速度。请注意,预解析器不会修改 DOM 树,而是将这项工作交由主解析器处理;预解析器只会解析外部资源(例如外部脚本、样式表和图片)的引用。

3、样式表

另一方面,样式表有着不同的模型。理论上来说,应用样式表不会更改 DOM 树,因此似乎没有必要等待样式表并停止文档解析。但这涉及到一个问题,就是脚本在文档解析阶段会请求样式信息。如果当时还没有加载和解析样式,脚本就会获得错误的回复,这样显然会产生很多问题。这看上去是一个非典型案例,但事实上非常普遍。Firefox 在样式表加载和解析的过程中,会禁止所有脚本。而对于 WebKit 而言,仅当脚本尝试访问的样式属性可能受尚未加载的样式表影响时,它才会禁止该脚本。

4、呈现树构建

在 DOM 树构建的同时,浏览器还会构建另一个树结构:呈现树。这是由可视化元素按照其显示顺序而组成的树,也是文档的可视化表示。它的作用是让您按照正确的顺序绘制内容。

Firefox 将呈现树中的元素称为“框架”。WebKit 使用的术语是呈现器或呈现对象。
呈现器知道如何布局并将自身及其子元素绘制出来。

四、布局

呈现器在创建完成并添加到呈现树时,并不包含位置和大小信息。计算这些值的过程称为布局或重排。

HTML 采用基于流的布局模型,这意味着大多数情况下只要一次遍历就能计算出几何信息。处于流中靠后位置元素通常不会影响靠前位置元素的几何特征,因此布局可以按从左至右、从上至下的顺序遍历文档。但是也有例外情况,比如 HTML 表格的计算就需要不止一次的遍历。

坐标系是相对于根框架而建立的,使用的是上坐标和左坐标。

布局是一个递归的过程。它从根呈现器(对应于 HTML 文档的 html> 元素)开始,然后递归遍历部分或所有的框架层次结构,为每一个需要计算的呈现器计算几何信息。

根呈现器的位置左边是 0,0,其尺寸为视口(也就是浏览器窗口的可见区域)。
所有的呈现器都有一个“layout”或者“reflow”方法,每一个呈现器都会调用其需要进行布局的子代的 layout 方法。

五、绘制

在绘制阶段,系统会遍历呈现树,并调用呈现器的“paint”方法,将呈现器的内容显示在屏幕上。绘制工作是使用用户界面基础组件完成的。

个人理解总结

一、解析器与预解析机制

呈现引擎从网络层获取请求文档的内容,然后开始解析 HTML 文档,并将各标记逐个转化为 DOM树(内容树)上的 DOM 节点,同时也会解析外部 CSS 文件以及样式元素中的样式数据。HTML 中这些带有视觉指令的样式信息将用于创建另一个树结构:渲染树(呈现树)。呈现树构建完毕之后,呈现引擎将对呈现树进行布局和绘制。

呈现引擎 的解析包括 HTML 解析和 CSS 解析,HTML 解析器的输出“解析树”是由 DOM 元素和属性节点构成的树结构,DOM 是文档对象模型 (Document Object Model) 的缩写。它是 HTML 文档的对象表示,同时也是外部内容(例如 JavaScript)与 HTML 元素之间的接口。解析树的根节点是“Document”对象。CSS 解析器会将 CSS 样式文件和样式元素中的样式数据解析为 CSS 规则树,浏览器结合 CSS 规则树和 DOM 树生成渲染树。

JavaScript 解释器 用于解析和执行 JavaScript 代码。

Android WebView实例详解 中文WORD版
Android WebView实例详解 中文WORD版

本文档主要讲述的是Android WebView实例详解;Android手机中内置了一款高性能webkit内核浏览器,在SDK中封装为一个叫做WebView组件。 WebKit是Mac OS X v10.3及以上版本所包含的软件框架(对v10.2.7及以上版本也可通过软件更新获取)。 同时,WebKit也是Mac OS X的Safari网页浏览器的基础。WebKit是一个开源项目,主要由KDE的KHTML修改而来并且包含了一些来自苹果公司的一些组件。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来

下载

一般来讲,我们认为浏览器从网络层接收到 HTML 文档内容,然后开始解析文档生成 DOM 树,遇到 CSS 样式表标签或 JS 脚本标签就起新线程去下载它们,并继续构建 DOM 树,浏览器根据 DOM 树构建渲染树,最后浏览器将渲染书绘制到用户界面。

在上述描述中,需要着重指出的是,HTML  文档的解析和渲染是一个渐进的过程。为达到更好的用户体验,呈现引擎会力求尽快将内容显示在屏幕上。它不必等到整个 HTML 文档解析完毕,就会开始构建呈现树和设置布局。在不断接收和处理来自网络的其余内容的同时,呈现引擎会将部分内容解析并显示出来。

浏览器的预解析。WebKit 和 Firefox 都进行了这项优化。在执行脚本时,其他线程会解析 HTML 文档的其余部分,找出并加载需要通过网络加载的其他资源。通过这种方式,资源可以在并行连接上加载,从而提高总体速度。请注意,预解析器不会修改 DOM 树,而是将这项工作交由主解析器处理;预解析器只会解析外部资源(例如外部脚本、样式表和图片)的引用。

浏览器的预解析可以减缓渲染被阻塞的情况,例如文档解析过程中预加载器发现了 标签,会对 last.js 文件进行加载并放在浏览器缓存中,这样当解析器遇到这个

二、CSS 和 JS 的处理顺序和阻塞分析

HTML 文档的解析和渲染过程中,外部样式表和脚本 顺序执行、并发加载

JS 脚本会阻塞 HTML 文档的解析,包括 DOM 树的构建和渲染树的构建;CSS 样式表会阻塞渲染树的构建,但 DOM 树依然继续构建(除非遇到 script 标签且 css 文件此时仍未加载完成),但不会渲染绘制到页面上。

在 HTML 文档的解析过程中,解析器遇到

理论上来说,应用样式表不会更改 DOM 树,因此似乎没有必要等待样式表并停止文档解析。但这涉及到一个问题,就是脚本在文档解析阶段会请求样式信息。如果当时还没有加载和解析样式,脚本就会获得错误的回复,这样显然会产生很多问题。这看上去是一个非典型案例,但事实上非常普遍。Firefox 在样式表加载和解析的过程中,会禁止所有脚本。而对于 WebKit 而言,仅当脚本尝试访问的样式属性可能受尚未加载的样式表影响时,它才会禁止该脚本。

但无论是哪种情况导致的阻塞,该加载的外部资源还是会加载,例如外部脚本、样式表和图片。HTML 文档的解析可能会被阻塞,但外部资源的加载不会被阻塞。

CSS 外部样式表的加载会阻塞外部脚本的执行,但并不会阻塞外部脚本的加载。这一点可以通过 chrome 调试工具中的 Network - Waterfall 进行验证,但是需要注意 chrome 的并发连接数(同一域名)上限为 6 个。

2125958182-5c98f0fc14454_articlex.png

并发加载-1.png

由上面两张截图可以看到,jquery.min.js 脚本文件与 bootstrap.css 等样式文件并行加载,但是由于 chrome 的并发连接数上限为 6 个,因此 bootstrap.min.js 脚本、xxx.css 样式等文件的加载会等待前面的文件加载完成,有可用连接数的时候才开始加载。

并发加载-2.png

了解以上信息之后,我们可以对该页面进行相应优化,例如对CSS文件进行压缩处理、使用 CDN,将资源分布在多个域名下、合并 CSS 文件,减少 HTTP 请求数量等,来提高 CSS 的加载速度,减少 HTML 文档解析和渲染的阻塞时间。

browser only allows six TCP connections per origin on HTTP 1.

浏览器的并发请求数目限制是针对同一域名的。因此可以使用 CDN 加速技术来提高用户访问网站的响应速度,这样使用了 CDN 的资源加载不会占用当前域名下的并发连接数,从而减少阻塞的时间。

网页性能

了解 HTML 文档的解析和渲染的过程对于分析网页性能有着重要意义,它可以帮助我们找到影响网页性能的关键因素。例如,我们知道 JS 外部脚本的执行会阻塞文档的解析,那么重量级的第三方插件则会影响首页加载的速度,如果因此影响到了用户体验,我们就需要考虑这个第三方插件的使用成本是不是太高了,能否使用其他轻量级的插件进行替代,或者只使用其中一部分模块。

以 Datatables 为例:

network.PNG

上图是一个项目页面的 Network 截图,红色框中的部分出现了约 700ms 左右的空白,我们需要知道为什么页面的加载会出现这样的情况,这段空白时间浏览器在干什么?

我们分析 Timeline 图,看看浏览器在这段时间的具体信息,如下:

timeline.PNG

通过 Timeline 图我们可以看到,在 250ms~900ms 时间区间内,浏览器在执行 datatables.min.js 脚本代码,这个脚本的执行阻塞了文档的解析,耗时约 700ms,对应了 Network 图中的空白。

我们继续查看页面总的耗时时间,评估 700ms 耗时的影响,如下:

performance.PNG

可以看到,页面总的完成耗时为 1.66s,由此可知 datatables.min.js 的执行耗时占了很大比重,应当慎重考虑是否一定要使用这个插件,能否使用其他轻量级的插件进行替代,或者能否精简插件的不必要模块,或者舍弃插件的使用。

参考资料-1
浏览器接收到html代码,可能是一份完整的文档,也可能是一个chunk,即开始解析。解析过程是先构建dom树,再根据dom树构建渲染树,最后浏览器将渲染树绘制到页面上。
构建dom树的过程即根据html代码自上而下进行构建,当遇到script文件加载/执行会阻塞后面dom树的构建(javascript可能会改变dom树),而遇到css文件则会阻塞渲染树的构建,即dom树依然继续构建(除非遇到script标签并且css文件依旧未加载完成),但不会渲染绘制到页面上。而无论哪个阻塞,该加载的文件还是会加载,例如html文档中的其他css/js/图片文件。
另外javascript被加载后就会被执行,执行的过程也阻塞树的构建。是执行完了才解析其他内容,而不是执行完了才加载其他内容。

作者:加冰
链接:https://www.zhihu.com/questio...

参考资料-2
首先,开源浏览器一般以8k每块下载html页面。
然后解析页面生成DOM树,遇到css标签或JS脚本标签就新起线程去下载他们,并继续构建DOM。
下载完后解析CSS为CSS规则树,浏览器结合CSS规则树和DOM树生成Render Tree。
注意:构建CSS Object Model(CSSOM)会阻塞JavaScript的执行。JavaScript的执行也会阻塞DOM的构建。
JavaScript下载后可以通过DOM API修改DOM,通过CSSOM API修改样式作用域Render Tree。
每次修改会造成Render Tree的重新布局和重绘。只要修改DOM或修改了元素的形状或大小,就会触发Reflow,单纯修改元素的颜色只需Repaint一下(调用操作系统Native GUI的API绘制)。

作者:陈金
链接:https://www.zhihu.com/questio...

本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的JavaScript视频教程栏目!

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2690

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1663

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1525

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

954

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1420

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1235

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1509

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1306

2023.11.13

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

3

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3.9万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.3万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号