浏览器渲染流程

2017-08-09

浏览器加载渲染过程

  • 自上而下加载,加载过程中解析渲染
  • 加载中遇到外部css,img会发出异步请求,不会影响文档加载
  • 加载中遇到js文件会挂起渲染进程,要等js加载和执行完,才恢复html渲染线程(因为js会修改DOM,document.write,解决方法是把js引用放在</body>前)
  • css加载不影响js文件加载,但却影响js文件的执行,即使js只有一行代码也会造成阻塞
    • 原因:$(“#id”).width(),js执行前,css必须下载解析完成,这事css阻塞后续js的原因。解决办法:当js不需要依赖css时可以放在头部css前面
  • 不要在外部调用的js文件中调用运行时间较长的函数,如果一定要用,可以使用setTimeout函数。
  • 原因:浏览器有以上五个常驻线程
    • 浏览器GUI渲染线程
    • javascript引擎线程
    • 浏览器定时器触发线程(setTimeout)
    • 浏览器事件触发线程
    • 浏览器http异步请求线程(.jpg <link />这类请求)
    • 这里也涉及到 阻塞 的现象,当js引擎线程(第二个)进行时,会挂起其他一切线程,这个时候3、4、5这三类线线程也会产生不同的异步事件(这句话不懂啊),由于 javascript引擎线程为单线程,所以代码都是先压到队列,采用先进先出的方式运行,事件处理函数,timer函数也会压在队列中,不断的从队头取出事件,这就叫:javascript-event-loop。
  • 现代浏览器存在 prefetch 优化,浏览器会另外开启线程,提前下载js、css文件,需要注意的是,预加载js并不会改变dom结构,他将这个工作留给主加载。
  • 如果js不会改变文档,可以在script标签加 defer 使浏览器先在加载后面的文档

解析

  • html文档解析生成解析树即dom树,是由dom元素及属性节点组成,树的根是document对象。
  • css解析将css文件解析为样式表对象。该对象包含css规则,该规则包含选择器和声明对象。
  • js解析因为文件在加载的同时也进行解析,详看js加载部分。

####渲染

  • 渲染最大的一个困难就是为每一个dom节点计算符合他的最终样式。
#test p{ color:#999999}
  • 遍历是自右向左,也就是先查询到p元素,再找到上一级id为test的元素。css解析时,生成的样式对象,从树的低端向上遍历。
    • 样式数据是非常大的结构,保存这样是的数据是很耗内存
    • 选择器迭代太深,造成太多的无用遍历
    • 样式规则涉及非常复杂的级联,定义了规则的层次
    • 渲染过程中,webkit使用一个标志位标志所有顶层样式都已经被加载完毕,如果dom元素进行attach时,css元素并没有被加载完毕,则放置占位符,并在文档中标记,当样式表加载完毕,则重新进行计算。
    • 说明:文档的渲染还是要等待顶层css加载完毕。
    • 页面的渲染 需要首先生成dom树,再由css生成CSSOM,最后两个一起生成render tree。