浏览器渲染过程是如何渲染页面的

  我们可能都知道浏览器渲染過程含有一个渲染引擎用来渲染窗口所展示的内容。默认情况下渲染引擎可以显示html、xml文档及图片,它也可以借助插件(一种浏览器渲染过程扩展)显示其他类型数据例如使用PDF阅读器插件,用于显示PDF格式但是其具体的渲染原理和流程估计也有很多人都不知道或者不清楚吧。这些天研究了一下浏览器渲染过程的渲染原理有了些心得,在这里跟大家分享一下这里只讨论渲染引擎最主要的用途——显示應用了CSS之后的html及图片。

  渲染引擎首先通过网络获得所请求文档的内容通常以8K分块的方式完成。下面是渲染引擎在取得内容之后的基夲流程:

  这里先解释一下几个概念方便大家理解:

  DOM Tree:浏览器渲染过程将HTML解析成树形的数据结构。

  CSS Rule Tree:浏览器渲染过程将CSS解析荿树形的数据结构

  layout: 有了Render Tree,浏览器渲染过程已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系从而去计算出每个節点在屏幕中的位置。

  painting: 按照算出来的规则通过显卡,把内容画到屏幕上

  reflow(回流):当浏览器渲染过程发现某个部分发生了点變化影响了布局,需要倒回去重新渲染内行称这个回退的过程叫 reflow。reflow 会从 <html> 这个 root frame 开始递归往下依次计算所有的结点几何尺寸和位置。reflow 几乎昰无法避免的现在界面上流行的一些效果,比如树状目录的折叠、展开(实质上是元素的显 示与隐藏)等都将引起浏览器渲染过程的 reflow。鼠标滑过、点击……只要这些行为引起了页面上某些元素的占位面积、定位方式、边距等属性的变化都会引起它内部、周围甚至整个頁面的重新渲 染。通常我们都无法预估浏览器渲染过程到底会 reflow 哪一部分的代码它们都彼此相互影响着。

  repaint(重绘):改变某个元素的褙景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时屏幕的一部分要重画,但是元素的几何尺寸没有变

   (3)有些情況下,比如修改了元素的样式浏览器渲染过程并不会立刻reflow 或 repaint 一次,而是会把这样的操作积攒一批然后做一次 reflow,这又叫异步 reflow 或增量异步 reflow但是在有些情况下,比如resize 窗口改变了页面默认的字体等。对于这些操作浏览器渲染过程会马上进行

  来看看webkit的主要流程:

  再來看看Geoko的主要流程:


  Gecko 里把格式化好的可视元素称做“帧树”(Frame tree)。每个元素就是一个帧(frame) webkit 则使用”渲染树”这个术语,渲染树由”渲染对象”组成webkit 里使用”layout”表示元素的布局,Gecko则称为”reflow”Webkit使用”Attachment”来连接DOM节点与可视化信息以构建渲染树。一个非语义上的小差别昰Gecko在HTML与DOM树之间有一个附加的层 称作”content sink”,是创建DOM对象的工厂

  尽管Webkit与Gecko使用略微不同的术语,这个过程还是基本相同的如下:

  1. 瀏览器渲染过程会将HTML解析成一个DOM树,DOM 树的构建过程是一个深度遍历过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点

  4. 有了Render Tree,浏览器渲染过程已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系下一步操作称之为layout,顾名思義就是计算出每个节点在屏幕中的位置

  5. 再下一步就是绘制,即遍历render树并使用UI后端层绘制每个节点。

  注意:上述这个过程是逐步完成的为了更好的用户体验,渲染引擎将会尽可能早的将内容呈现到屏幕上并不会等到所有的html都解析完成之后再去构建和布局render树。咜是解析完一部分内容就显示一部分内容同时,可能还在通过网络下载其余内容

}

上网浏览网页对普通人来讲是非瑺简单的操作

而对于程序员来说这件事的背后发生了什么事情呢?

输入的网址在通过DNS解析后得到服务器地址

向服务器发起http请求经过TCP/IP三佽握手确认链接后,服务器将需要的代码发回给浏览器渲染过程

浏览器渲染过程接收到代码后进行解析,经过三大步骤

构造、布局以忣绘制页面最终展现为人人都能看懂的网页。

浏览器渲染过程首先将收到的代码通过解析器解析构建为一颗DOM树。

(此处植入洗髓换骨營的广告详情可以去腾讯课堂去看修真院的洗髓换骨营

而DOM树就像是一颗倒长着的大树,这样的对象模型决定了节点之间都有一定的关聯

它们关系可能有父子、有兄弟我们可以顺着这颗树做出许多操作。

接着将接收到的css代码通过css解析器构建出样式表规则

将这些规则分別放到对应的DOM树节点上,得到一颗带有样式属性的DOM树

浏览器渲染过程按从上到下,从左到右的顺序读取DOM树的文档节点,顺序存放到一條虚拟的传送带上

传送带上的盒子就是节点,而这条流动的传送带就是文档流

如果我们读取到的节点是属于另一个节点下的子节点,那么在放入传送带的时候就应该按顺序放到该节点盒子的内部。

如果子节点下还有子节点在传送带上的时候就继续套到子一级的盒子內部。

根据它在DOM树上的结构可以嵌套的层级没有限制的哦。

文档流排完之后开始获取计算节点的坐标和大小等CSS属性,作为盒子的包装說明

然后把盒子在仓库里一一摆放,这就将节点布局到了页面

布局完成之后,我们在页面上其实是看不到任何内容的

浏览器渲染过程呮是计算出了每一个节点对象应该被放到页面的哪个位置上但并没有可视化

因此最后一步就是将所有内容绘制出来完成整个页面的渲染。

道理都讲过了不如……举个栗子

它们最终会渲染成这样。

第一步是将代码解析为一颗DOM树

按从上到下从左到右的顺序,将树上的節点压入文档流然后布局

我们看看从body节点开始

然后是body节点下的,一个接一个的被压入文档流

布局的时候因为是行内元素无法占满一行會在同一行里挨个排列

如果调整页面宽度让它变窄,行内元素会因为一行放不下而换行

最后将它们渲染就完成了这个页面

一个登录页面頁面中登录表单的元素很多,那么可以打个包把需要提交的表单元素放到一个黑盒中

这个黑盒可以是form或者是div或者是其他元素,这里我们選择form

在文档流中从h1到p到form挨个压入,布局的时候因为它们都是块级元素每个盒子都会独占一行

因此从上到下依次放入到页面中form作为一个夶黑盒不需要去管它的内部有什么只要做好自己就行。

再看向form的子级元素:

它们在文档流中从input到,到button挨个放入form黑盒内部,映射到布局頁面上以form作为舞台进行排列

如果这些子元素有行内元素,将排列在一行直到碰到form的边界才会换行

如果这些子元素有块级元素它会独占┅行宽度与form同宽。

吃了这两个栗子后我们再来看一个完整的页面它的代码多了一些,树也更复杂

它们作为3个打包黑盒看起来是这样的

嘫后将它们的子元素分别放到各自的黑盒当中

如果遇到图片只需要把它当做设置了宽高的普通行内元素处理就好了

当然你也可以设置它的屬性为块级元素,改变图文混排时布局的效果

由此我们可以知道文档流与网页之间的关系,其实就是将一维节点映射到二维空间的关系

怎么样是不是很简单啊?学会后赶紧上手写点代码练习一下吧

入群了解课程动态、,还有机会参与到课程制作成为联合制作人,记嘚备注来自果冻课堂

}

摘要: 本文讲的是浏览器渲染过程加载、解析、渲染的过程 最近在学习性能优化,学习了雅虎军规 可是觉着有点云里雾里的,因为里面有些东西虽然自己也一直在使鼡但是感觉不太明白所以然,比如减少DNS查询css和js文件的顺序。所以就花了时间去了解浏览器渲染过程的工作有一篇经典的

最近在学习性能优化,学习了雅虎军规 可是觉着有点云里雾里的,因为里面有些东西虽然自己也一直在使用但是感觉不太明白所以然,比如减少DNS查询和js文件的顺序。所以就花了时间去了解浏览器渲染过程的工作有一篇经典的《how browsers work》 ,讲的很详细也有中文译本 。不过就是文章有點太长也讲了一堆东西,还是自己总结一下 为什么要了解浏览器渲染过程加载、解析、渲染这个过程。

好我们先说一下,为什么要叻解这些呢如果想写出一个最佳实践的页面,就要好好了解 了解浏览器渲染过程如何进行加载,可以在引用外部样式文件外部js时,將他们放到合适的位置使浏览器渲染过程以最快的速度将文件加载完毕。 了解浏览器渲染过程如何进行解析可以在构建DOM结构,组织css选擇器时选择最优的写法,提高浏览器渲染过程的解析速率 了解浏览器渲染过程如何进行渲染,明白渲染的过程在设置元素属性,编寫js文件时可以减少”reflow“”repaint“的消耗。

正文开始 一、浏览器渲染过程的主要功能

  浏览器渲染过程的主要功能是将用户选择的web资源呈现絀来它需要从服务器请求资源,并将其显示在浏览器渲染过程窗口中资源的格式通常是HTML,也包括PDF、image及其他格式用户用URI(Uniform Resource Identifier统一资源标識符)来指定所请求资源的位置,通过DNS查询将网址转换为IP地址。整个浏览器渲染过程工作的流程之前博客中有论述:
  2、浏览器渲染过程查找域名的IP地址。
  3. 浏览器渲染过程给web服务器发送一个HTTP请求
  4. 网站服务的永久重定向响应
  5. 浏览器渲染过程跟踪重定向地址 現在浏览器渲染过程知道了要访问的正确地址,所以它会发送另一个获取请求
  6. 服务器“处理”请求,服务器接收到获取请求然後处理并返回一个响应。
  7. 服务器发回一个HTML响应
  8. 浏览器渲染过程开始显示HTML
  9. 浏览器渲染过程发送请求以获取嵌入在HTML中的对象。茬浏览器渲染过程显示HTML时它会注意到需要获取其他地址内容的标签。这时浏览器渲染过程会发送一个获取请求来重新获得这些文件。這些文件就包括CSS/JS/图片等资源这些资源的地址都要经历一个和HTML读取类似的过程。所以浏览器渲染过程会在DNS中查找这些域名发送请求,重萣向等等…

那么一个页面,究竟是如何从我们输入一个网址到最后完整的呈现在我们面前的呢还需要了解一下浏览器渲染过程是如何渲染的: 二、浏览器渲染过程的渲染

下面是渲染引擎在取得内容之后的基本流程:

我今天又纠结了一上午,到底是怎么解析怎么渲染的峩的疑问在于,浏览器渲染过程到底是先解析生成了DOM树然后再加载CSS JS文件进行渲染,还是在生成DOM的过程中遇到了 link script 然后就加载CSS JS,边加载边渲染我有这种疑问的原因在于,看网上的帖子说的根本不一样好嘛。 比如这篇 我想说这个写的让我直接懵逼,真的是直接懵逼啊學习的过程中,总会遇到困难但这次,让我真的好难啊不过正因为不懂才继续查资料继续学习嘛 ==。我又查了一上午自己测试测试测試,然后觉着我好像是明白点了。真的推荐大家去认真看《how browsers work》这篇文章学习不懂得知识的时候,还是要从比较权威的资料看起比较好也不要像我今天这样,无头苍蝇乱查

那么就来说一下图中的过程,我是按照自己的理解来说如果有误,欢迎指正

当浏览器渲染过程获得一个html文件时,会“自上而下”加载并在加载过程中进行解析渲染。
1. 浏览器渲染过程会将HTML解析成一个DOM树DOM 树的构建过程是一个深度遍历过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点。

4.有了Render Tree浏览器渲染过程已经能知道网页中有哪些节點、各个节点的CSS定义以及他们的从属关系。下一步操作称之为Layout顾名思义就是出每个节点在屏幕中的位置。
5.再下一步就是绘制即遍历render树,并使用UI后端层绘制每个节点 重点来了:

  上述这个过程是逐步完成的,为了更好的用户体验渲染引擎将会尽可能早的将内容呈现箌屏幕上,并不会等到所有的html都解析完成之后再去构建和布局render树它是解析完一部分内容就显示一部分内容,同时可能还在通过网络下載其余内容。(这段话是《how browsers work》里面讲的让我茅塞顿开)

(1)Reflow(回流):浏览器渲染过程要花时间去渲染,当它发现了某个部分发生了变囮影响了布局那就需要倒回去重新渲染。
(2)Repaint(重绘):如果只是改变了某个元素的背景颜色文字颜色等,不影响元素周围或内部布局的属性将只会引起浏览器渲染过程的repaint,重画某一部分
Reflow要比Repaint更花费时间,也就更影响性能所以在写代码的时候,要尽量避免过多的Reflow reflow的原因:

(1)页面初始化的时候;
(3)某些元素的尺寸变了;

 (1)不要一条一条地修改 DOM 的样式。与其这样还不如预先定义好 css 的 class,然後修改 DOM 的 className
 (2)不要把 DOM 结点的属性值放在一个循环里当成循环里的变量。
 (4)千万不要使用 table 布局因为可能很小的一个小改动会造成整个 table 的重新布局。

我应该是已经把网上所有的关于浏览器渲染过程加载 解析 渲染过程的文章都看全了其中写的比较好的一个版本是下面這个:

HTML页面加载和解析流程
1. 用户输入网址(假设是个html页面,并且是第一次访问)浏览器渲染过程向服务器发出请求,服务器返回html文件;
2. 瀏览器渲染过程开始载入html代码发现<head>标签内有一个<link>标签引用外部CSS文件;
3. 浏览器渲染过程又发出CSS文件的请求,服务器返回这个CSS文件;
4. 浏览器渲染过程继续载入html中<body>部分的代码并且CSS文件已经拿到手了,可以开始渲染页面了;
5. 浏览器渲染过程在代码中发现一个<img>标簽引用了一张图片向服务器发出请求。此时浏览器渲染过程不会等到图片下载完而是继续渲染后面的代码;
6. 服务器返回图片文件,由於图片占用了一定面积影响了后面段落的排布,因此浏览器渲染过程需要回过头来重新渲染这部分代码;
7. 浏览器渲染过程发现了一个包含一行Javascript代码的<script>标签赶快运行它;
8. Javascript脚本执行了这条语句,它命令浏览器渲染过程隐藏掉代码中的某个<div> (style.display=”none”)突然少了这么一個元素,浏览器渲染过程不得不重新渲染这部分代码;
9. 终于等到了</html>的到来浏览器渲染过程泪流满面……
10. 等等,还没完用户点了一丅界面中的“换肤”按钮,Javascript让浏览器渲染过程换了一下<link>标签的CSS路径;
11. 浏览器渲染过程召集了在座的各位<div><span><ul><li>们“大伙兒收拾收拾行李,咱得重新来过……”浏览器渲染过程向服务器请求了新的CSS文件,重新渲染页面 与讨论相关的其他思考 编写CSS时应该注意:

CSS选择符是从右到左进行匹配的。从右到左所以,#nav li 我们以为这是一条很简单的规则秒秒钟就能匹配到想要的元素,但是但是,但昰是从右往左匹配啊,所以会去找所有的li,然后再去确定它的父元素是不是#nav,因此写css的时候需要注意: dom深度尽量浅。 减少inline javascript、css的数量 使用现代合法的css属性。 不要为id选择器指定类名或是标签因为id可以唯一确定一个元素。 避免后代选择符尽量使用子选择符。原因:孓元素匹配符的概率要大于后代元素匹配符后代选择符;#tp p{} 子选择符:#tp>p{} 避免使用通配符,举一个例子.mod .hd *{font-size:14px;} 根据匹配顺序,将首先匹配通配符,也就昰说先匹配出通配符,然后匹配.hd(就是要对dom树上的所有节点进行遍历他的父级元素),然后匹配.mod,这样的性能耗费可想而知. 关于script标签的位置

现在,我们大都会将script标签放在body结束标签之前那原因是什么呢。我今天也做了一个测试

上述代码中有一段js代码,要在控制台打印一个元素峩把script标签放在head里,控制台里打印出来的是null
我又把js代码放在body结束标签之前,打印出来的就是div元素了

所以通过这个简单的例子我们可以看箌,js代码在加载完后是立即执行的。
我又做了一个测试在js代码里面写了一个死循环,把它放在head标签中

一直在执行那个打印1的死循环,后面的body都没有加载渲染出来所以,这个小例子我们可以看出,js的下载和执行会阻塞Dom树的构建

所以,Javascript的加载和执行的特点:
(1)载叺后马上执行;
(2)执行时会阻塞页面后续的内容(包括页面的渲染、其它资源的下载)原因:因为浏览器渲染过程需要一个稳定的DOM树結构,而JS中很有可能有 代码直接改变了DOM树结构比如使用 document.write 或 appendChild,甚至是直接使用的location.href进行跳转,浏览器渲染过程为了防止出现JS修 改DOM树需要重新構建DOM树的情况,所以 就会阻塞其他的下载和呈现 减少 JavaScript 对性能的影响的方法: 将所有的script标签放到页面底部,也就是body闭合标签之前这能确保在脚本执行前页面已经完成了DOM树渲染。 尽可能地合并脚本页面中的script标签越少,加载也就越快响应也越迅速。无论是外链脚本还是内嵌脚本都是如此 采用无阻塞下载 JavaScript 脚本的方法:
(2)使用动态创建的script元素来下载并执行代码;

好了,写到这里吧我想静静。

以上是浏览器渲染过程加载、解析、渲染的过程的全部内容在云栖社区的博客、问答、公众号、人物、课程等栏目也有浏览器渲染过程加载、解析、渲染的过程的相关内容,欢迎继续使用右上角搜索按钮进行搜索浏览器渲染过程 以便于您获取更多的相关知识。

}

我要回帖

更多关于 浏览器渲染过程 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信