浏览器的主要组件为:javascript
值得注意的是,和大多数浏览器不一样,Chrome 浏览器的每一个标签页都分别对应一个呈现引擎实例。每一个标签页都是一个独立的进程。css
呈现引擎一开始会从网络层获取请求文档的内容,内容的大小通常限制在 8000 个块之内。html
而后进行以下所示的基本流程:html5
呈现引擎将开始解析 HTML 文档,并将各标记逐个转化成“内容树”上的 DOM 节点。同时也会解析外部 CSS 文件以及样式元素中的样式数据。HTML 中这些带有视觉指令的样式信息将用于建立另外一个树结构:呈现树。java
呈现树包含多个带有视觉属性(如颜色和尺寸)的矩形。这些矩形的排列顺序就是它们将在屏幕上显示的顺序。jquery
呈现树构建完毕以后,进入“布局”处理阶段,也就是为每一个节点分配一个应出如今屏幕上的确切坐标。下一个阶段是绘制 - 呈现引擎会遍历呈现树,由用户界面后端层将每一个节点绘制出来。web
须要着重指出的是,这是一个渐进的过程。为达到更好的用户体验,呈现引擎会力求尽快将内容显示在屏幕上。它没必要等到整个 HTML 文档解析完毕以后,就会开始构建呈现树和设置布局。在不断接收和处理来自网络的其他内容的同时,呈现引擎会将部份内容解析并显示出来。chrome
主流程示例:数据库
Firefox 将呈现树中的元素称为“框架”。WebKit 使用的术语是呈现器或呈现对象。
呈现器知道如何布局并将自身及其子元素绘制出来。bootstrap
呈现器在建立完成并添加到呈现树时,并不包含位置和大小信息。计算这些值的过程称为布局或重排。
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 代码。
通常来说,咱们认为浏览器从网络层接收到 HTML 文档内容,而后开始解析文档生成 DOM 树,遇到 CSS 样式表标签或 JS 脚本标签就起新线程去下载它们,并继续构建 DOM 树,浏览器根据 DOM 树构建渲染树,最后浏览器将渲染书绘制到用户界面。
在上述描述中,须要着重指出的是,HTML 文档的解析和渲染是一个渐进的过程。为达到更好的用户体验,呈现引擎会力求尽快将内容显示在屏幕上。它没必要等到整个 HTML 文档解析完毕,就会开始构建呈现树和设置布局。在不断接收和处理来自网络的其他内容的同时,呈现引擎会将部份内容解析并显示出来。
浏览器的预解析。WebKit 和 Firefox 都进行了这项优化。在执行脚本时,其余线程会解析 HTML 文档的其他部分,找出并加载须要经过网络加载的其余资源。经过这种方式,资源能够在并行链接上加载,从而提升整体速度。请注意,预解析器不会修改 DOM 树,而是将这项工做交由主解析器处理;预解析器只会解析外部资源(例如外部脚本、样式表和图片)的引用。
浏览器的预解析能够减缓渲染被阻塞的状况,例如文档解析过程当中预加载器发现了 <script src="last.js"></script>
标签,会对 last.js 文件进行加载并放在浏览器缓存中,这样当解析器遇到这个 <script> 标记时,因为预加载器已经将 last.js 文件加载下来了,因此 last.js 会被当即执行,不须要等待从网络抓取资源,减缓了对渲染的阻塞。
HTML 文档的解析和渲染过程当中,外部样式表和脚本 顺序执行、并发加载。
JS 脚本会阻塞 HTML 文档的解析,包括 DOM 树的构建和渲染树的构建;CSS 样式表会阻塞渲染树的构建,但 DOM 树依然继续构建(除非遇到 script 标签且 css 文件此时仍未加载完成),但不会渲染绘制到页面上。
在 HTML 文档的解析过程当中,解析器遇到 <script> 标记时会当即解析并执行脚本,HTML 文档的解析将被阻塞,直到脚本执行完毕。若是脚本是外部的,那么解析过程会中止,直到从网络抓取资源并解析和执行完成后,再继续解析后续内容。
理论上来讲,应用样式表不会更改 DOM 树,所以彷佛没有必要等待样式表并中止文档解析。但这涉及到一个问题,就是脚本在文档解析阶段会请求样式信息。若是当时尚未加载和解析样式,脚本就会得到错误的回复,这样显然会产生不少问题。这看上去是一个非典型案例,但事实上很是广泛。Firefox 在样式表加载和解析的过程当中,会禁止全部脚本。而对于 WebKit 而言,仅当脚本尝试访问的样式属性可能受还没有加载的样式表影响时,它才会禁止该脚本。
但不管是哪一种状况致使的阻塞,该加载的外部资源仍是会加载,例如外部脚本、样式表和图片。HTML 文档的解析可能会被阻塞,但外部资源的加载不会被阻塞。
CSS 外部样式表的加载会阻塞外部脚本的执行,但并不会阻塞外部脚本的加载。这一点能够经过 chrome 调试工具中的 Network - Waterfall 进行验证,可是须要注意 chrome 的并发链接数(同一域名)上限为 6 个。
由上面两张截图能够看到,jquery.min.js 脚本文件与 bootstrap.css 等样式文件并行加载,可是因为 chrome 的并发链接数上限为 6 个,所以 bootstrap.min.js 脚本、xxx.css 样式等文件的加载会等待前面的文件加载完成,有可用链接数的时候才开始加载。
了解以上信息以后,咱们能够对该页面进行相应优化,例如对CSS文件进行压缩处理、使用 CDN,将资源分布在多个域名下、合并 CSS 文件,减小 HTTP 请求数量等,来提升 CSS 的加载速度,减小 HTML 文档解析和渲染的阻塞时间。
browser only allows six TCP connections per origin on HTTP 1.
浏览器的并发请求数目限制是针对同一域名的。所以可使用 CDN 加速技术来提升用户访问网站的响应速度,这样使用了 CDN 的资源加载不会占用当前域名下的并发链接数,从而减小阻塞的时间。
了解 HTML 文档的解析和渲染的过程对于分析网页性能有着重要意义,它能够帮助咱们找到影响网页性能的关键因素。例如,咱们知道 JS 外部脚本的执行会阻塞文档的解析,那么重量级的第三方插件则会影响首页加载的速度,若是所以影响到了用户体验,咱们就须要考虑这个第三方插件的使用成本是否是过高了,可否使用其余轻量级的插件进行替代,或者只使用其中一部分模块。
以 Datatables 为例:
上图是一个项目页面的 Network 截图,红色框中的部分出现了约 700ms 左右的空白,咱们须要知道为何页面的加载会出现这样的状况,这段空白时间浏览器在干什么?
咱们分析 Timeline 图,看看浏览器在这段时间的具体信息,以下:
经过 Timeline 图咱们能够看到,在 250ms~900ms 时间区间内,浏览器在执行 datatables.min.js 脚本代码,这个脚本的执行阻塞了文档的解析,耗时约 700ms,对应了 Network 图中的空白。
咱们继续查看页面总的耗时时间,评估 700ms 耗时的影响,以下:
能够看到,页面总的完成耗时为 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...