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

为什么要了解浏览器加载、解析、渲染这个过程?

好,我们先说一下,为什么要了解这些呢?如果想写出一个最佳实践的页面,就要好好了解。

  • 了解浏览器如何进行加载,可以在引用外部样式文件,外部js时,将他们放到合适的位置,使浏览器以最快的速度将文件加载完毕。
  • 了解浏览器如何进行解析,可以在构建DOM结构,组织css选择器时,选择最优的写法,提高浏览器的解析速率。
  • 了解浏览器如何进行渲染,明白渲染的过程,在设置元素属性,编写js文件时,可以减少”reflow“”repaint“的消耗。

正文开始

一、浏览器的主要功能

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

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

二、浏览器的渲染

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

 解析html以构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树

先来看个图:

所以,浏览器会解析三个东西: 
(1) HTML/SVG/XHTML,解析这三种文件会产生一个 DOM Tree。 
(2) CSS,解析 CSS 会产生 CSS 规则树。 
(3) JavaScript脚本,主要是通过 DOM API 和 CSSOM API 来操作 DOM Tree 和 CSS Rule Tree.


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

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

当浏览器获得一个html文件时,会“自上而下”加载,并在加载过程中进行解析渲染。 
解析: 
1. 浏览器会将HTML解析成一个DOM树,DOM 树的构建过程是一个深度遍历过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点。 
2. 将CSS解析成 CSS Rule Tree 。 
3. 根据DOM树和CSSOM来构造 Rendering Tree。注意:Rendering Tree 渲染树并不等同于 DOM 树,因为一些像 Header 或 display:none 的东西就没必要放在渲染树中了。

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

重点来了:

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

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

reflow的原因:

(1)页面初始化的时候; 
(2)操作DOM时; 
(3)某些元素的尺寸变了; 
(4)如果 CSS 的属性发生变化了。

减少 reflow/repaint

 (1)不要一条一条地修改 DOM 的样式。与其这样,还不如预先定义好 css 的 class,然后修改 DOM 的 className。 
 (2)不要把 DOM 结点的属性值放在一个循环里当成循环里的变量。 
 (3)为动画的 HTML 元件使用 fixed 或 absoult 的 position,那么修改他们的 CSS 是不会 reflow 的。 
 (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的时候需要注意:

  1. dom深度尽量浅。
  2. 减少inline javascript、css的数量。
  3. 使用现代合法的css属性。
  4. 不要为id选择器指定类名或是标签,因为id可以唯一确定一个元素。
  5. 避免后代选择符,尽量使用子选择符。原因:子元素匹配符的概率要大于后代元素匹配符。后代选择符;#tp p{} 子选择符:#tp>p{}
  6. 避免使用通配符,举一个例子,.mod .hd *{font-size:14px;} 根据匹配顺序,将首先匹配通配符,也就是说先匹配出通配符,然后匹配.hd(就是要对dom树上的所有节点进行遍历他的父级元素),然后匹配.mod,这样的性能耗费可想而知.

关于script标签的位置

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

<!DOCTYPE html>
<html>
<head> <meta charset="utf-8"> <title>测试js代码位置</title> <script type="text/javascript"> var item = document.getElementById("item"); cosole.log(item); </script> </head> <body> <div id="item" width="100px" height="100px"> 你好 </div> </body> </html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

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

转载于:https://www.cnblogs.com/larennani/p/6741289.html

浏览器加载、解析、渲染的过程相关推荐

  1. 浏览器加载解析渲染机制的全面解析

    (注1:如果有问题欢迎留言探讨,一起学习!本文首发于我的简书,转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录.) 1. 简介 在前面一篇文章中,讲到了用户从输入url到看到页面的 ...

  2. 浏览器加载和渲染html的顺序

    1.浏览器加载和渲染html的顺序 浏览器加载和渲染html的顺序 IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的. 在渲染到页面的某一部分时,其上面的所有部分都已经下载完成 ...

  3. 加载如下html 写出输出顺序,浏览器加载和渲染html的顺序-结论篇

    我只转载觉得可以使用的. 1.浏览器加载和渲染html的顺序 1.IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的. 2.在渲染到页面的某一部分时,其上面的所有部分都已经下载完 ...

  4. JS浏览器加载一个页面的过程

    加载过程->从上向下逐行进行加载 <!DOCTYPE html> <html><head><meta charset="UTF-8" ...

  5. 理解浏览器是如何加载及渲染网页的

    先上图,我们再慢慢解释,这图就是浏览器加载网页的一个过程 当我们在浏览器输入一个地址(比如:http://toadw.cn),那么点击回车后,浏览器是如何加载网页的呢? 加载过程 一开始浏览器是不知道 ...

  6. html中加载解析,HTML页面加载和解析流程详细介绍

    序言: 我一直都认为"网页制作"这个词是一个不怎么高端的词,在我的印象中网页制作的词是没有生命力的一个制作,我喜欢用HTML 这样简单直接,这词凸显高端,有大气漂亮的UI.一套完美 ...

  7. 转:浏览器加载页面的过程与页面性能优化

    本文是转帖,原文:http://www.baiduux.com/blog/2011/02/15/browser-loading/ 发布日期:2011年2月15日 作者:nwind 类别:HTML/CS ...

  8. 页面加载完毕_【前端面试】dom 的解析,加载,渲染

    本文会把 dom 的解析,加载,渲染结合 window.performance 一起讲. dom 的解析 解析:HTMl 解析器把 HTML 构建成 HTML 树形数据结构,也就是 DOM 树. 注意 ...

  9. 浏览器加载渲染HTML、DOM、CSS、 JAVASCRIPT、IMAGE、FLASH、IFRAME、SRC属性等资源的顺序总结...

    页面响应加载的顺序: 1.域名解析->加载html->加载js和css->加载图片等其他信息 DOM详细的步骤如下: 解析HTML结构. 加载外部脚本和样式表文件. 解析并执行脚本代 ...

最新文章

  1. 4.64Tomcat的日志
  2. 订餐系统之自动确认淘点点订单
  3. 将一个大文件分成若干个小文件方法
  4. 休眠锁定模式–乐观锁定模式如何工作
  5. NLP(新闻文本分类)——数据读取与数据分析
  6. python作品代码_学习python的一些心得体会
  7. Asp.Net MVC4 Bundle捆绑压缩技术
  8. wordpress配置HTTPS遇到问题解决方案
  9. 阿里软件测试工程师手把手教学——面试必问的 Linux 命令
  10. IMDB影评倾向分类 - N-Gram
  11. freeswitch智能语音开发之ASR
  12. Siri触发器原理及改进
  13. Labview NIvision视觉识别测距离模糊匹配VAS和VDM
  14. python平方数_【python】升序查找100内最大平方数的方法
  15. 引流脚本到底怎么样?是不是骗人的?没有效果?
  16. 论文学习 | 用于三维条纹图案轮廓快速测量的质量引导泛洪相位展开算法
  17. 报表汇总工具FineReport中下拉框如何显示多列
  18. 树莓派安装python3.8_python-在树莓派3上运行librosa和numba
  19. 人体声音生理学为基础的发声法
  20. 外国人来华工作签证办理流程

热门文章

  1. usaco The Castle
  2. ORB_SLAM2代码阅读(4)——LoopClosing线程
  3. c语言x在二进制表示下1的个数,算法:计算十进制数字在二进制表示1的个数,...
  4. oracle怎么adi导入,Web adi 导入笔记 详细图解
  5. es 时间字段聚合_Elasticsearch 聚合(aggregation)查询返回所有
  6. python规则网格插值_Python中规则网格上的插值
  7. android预置第三方apk,android 内置APK成系统应用
  8. 准确度判断 语义分割_Mask R-CNN(目标检测语义分割)测试
  9. 机器学习四剑客3——Pandas
  10. 使用OpenCV和Python高效计算视频的总帧数