浏览器页面加载解析渲染机制(一)

一:为什么要了解浏览器渲染页面和加载页面机制,主要还是性能的优化。

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

  这三个过程在实际进行的时候又不是完全独立,而是会有交叉。会造成一边加载,一边解析,一边渲染的工作现象。

二:用户访问网页都发生了什么。

  1. 用户访问网页,DNS服务器(域名解析系统)会根据用户提供的域名查找对应的IP地址,找到后,系统会向对应IP地址的网络服务器发送一个http请求。
  2. 网络服务器解析请求,并发送请求给数据库服务器。
  3. 数据库服务器将请求的资源返回给网络服务器,网络服务器解析数据,并生成html文件,放入http response中,返回给浏览器。
  4. 浏览器解析 http response。
  5. 浏览器解析 http response后,需要下载html文件,以及html文件内包含的外部引用文件,及文件内涉及的图片或者多媒体文件。(这里进入主题了也就是下面的第三大点)

  1~4步骤HTTP协议的一些内容,访问服务器端可能遭遇的问题:如果网络服务器无法获取数据库服务器返回的资源文件(http response 404),或者由于并发原因暂时无法处理用户的http请求(http response 500)。

三:浏览器渲染页面和解析加载页面机制。

  a.加载,即为获取资源文件的过程,不同浏览器,以及他们的不同版本在实现这一过程时,会有不同的实现效果(资源间互相阻塞,可以用timeline来做测试)。这里先说下浏览器的5个常驻线程:

  1. 浏览器GUI渲染线程
  2. javascript引擎线程
  3. 浏览器定时器触发线程(setTimeout)
  4. 浏览器事件触发线程
  5. 浏览器http异步请求线程(.jpg <link />这类请求)

  备注:现代浏览器存在 prefetch 优化,浏览器会另外开启线程,提前下载js、css文件,需要注意的是,预加载js并不会改变dom结构,他将这个工作留给主加载。

  注意:这里也涉及到 阻塞 的现象,当js引擎线程(第二个)进行时,会挂起其他一切线程,这个时候3、4、5这三类线程也会产生不同的异步事件,由于 javascript引擎线程为单线程,所以代码都是先压到队列,采用先进先出的方式运行,事件处理函数,timer函数也会压在队列中,不断的从队头取出事件,这就叫:javascript-event-loop。简单点说应该是当在进行第二线程的时候,1,3,4,5都会挂起,比如这时候触发click事件,即使先前JS已经加载完成,click事件会压在队列里,这里也要先完成第二线程才会执行click事件。

  加载顺序:

  1. 浏览器解析http response 下载html文件会”自上而下“加载,并在加载过程中进行解析渲染。“自上而下”加载时遇到图片、视频之类资源时便会进入第5个线程,这是异步请求,并不会影响html文档进行加载。
  2. 加载过程中遇到外部css文件,浏览器另外发出一个请求,来获取css文件。这里也是第5个线程,这里css解析会生成一个rule tree(规则树),这个以后会更新。
  3. 当文档加载过程中遇到js文件,html文档会挂起渲染(加载解析渲染同步)的线程,不仅要等待文档中js文件加载完毕,还要等待解析执行完毕,才可以恢复html文档的渲染线程。

  原因:JS有可能会修改DOM,最为经典的document.write,这意味着,在JS执行完成前,后续所有资源的下载可能是没有必要的,这是js阻塞后续资源下载的根本原因。
  办法:可以将外部引用的js文件放在</body>前。

  4. css可能影响js的执行造成阻塞。

  原因:如js里面var width = $('#id').width();这里js执行前,浏览器必须保证之前的css文件已下载和解析完成(后面的不会影响),这也是css阻塞后续js的根本原因。当js文件不需要依赖css文件时,可以将js文件放在头部css的前面。

  5. 预加载网页,利用空余时间来提前加载该网页的后续网页。

<link rel="prefetch" href="http://">

  6. 为js脚本添加defer属性,其不会阻塞后续DOM的的渲染。但是因为这个defer只是IE专用,所以一般用得比较少。而我们标准的的HTML5也加入了一个异步载入javascript的属性:async,无论你对它赋什么样的值,只要它出现,它就开始异步加载js文件。但是, async的异步加载会有一个比较严重的问题,那就是它忠实地践行着“载入后马上执行”这条军规,所以,虽然它并不阻塞页面的渲染,但是你也无法控制他执行的次序和时机。

<script defer="true" src="JavaScript.js" type="text/javascript"/>

  mark--zhq[2]。

 

posted @ 2015-12-23 13:17  诸葛正当年  阅读(5829)  评论(1编辑  收藏  举报