# 浏览器渲染页面的流程

# DOM

  1. 一般先请求服务器得到HTML文件,不过一开始浏览器得到的是显示字节内容的HTML文件
  2. 把字节转化为字符
  3. 浏览器把字符转换为Token,可以简单把Token理解为符号标签
  4. 把Token转换为节点对象
  5. 把节点对象连接在一起,形成文本对象模型(Document Object Model, DOM)

每个节点对象相连形成父子关系,如果之后要对某个节点对象进行操作,对于浏览器来说就非常友好了

# CSSOM

浏览器遇到link标签,浏览器会向服务器发生请求,得到CSS文件,后面的流程和处理HTML文件非常相似

  1. 一般先请求服务器得到CSS文件,不过一开始浏览器得到的是显示字节内容的HTML文件
  2. 把字节转化为字符
  3. 浏览器把字符转换为Token,可以简单把Token理解为符号标签
  4. 把Token转换为节点对象
  5. 把节点对象连接在一起,形成CSS对象模型(Cascading Style Sheets Object Model, CSSOM)

# 渲染树

页面就是要根据渲染树的结构样式来进行的,但是DOM和CSSOM不是简单的进行结合就好了,因为渲染树上的节点是页面能够呈现的内容,也就是一些HTML标签和某些样式是不会被呈现出来的(如mate和link标签),不呈现出来就不会被挂在渲染树上,渲染树的任务就是匹配DOM和CSSOM的节点,并且捕获可见内容

# 布局

在渲染树构造完以后是不能被马上渲染的,还要布局,也就是获取渲染树的结构、节点位置和大小,而布局是依据盒子模型来进行的,盒子在页面上排列和嵌套

# 绘制

把渲染树以像素的形式绘制在页面上,这样我们的网页就呈现出来了

# 提示

如果先返回并且解析完成JS文件也是会发生阻塞的,必须等到CSSOM构建完成了才能执行JS文件(因为渲染树需要DOM和CSSOM构建完成后才能构建),而且JS是可以控制DOM和CSS样式的。CSSOM的构建是渲染中一个重要的阻塞因素,但是DOM也会阻塞页面渲染,但是DOM可以部分解析,而且CSSOM不能部分解析,但是解析CSS文件的时候浏览器依然可以解析JS文件,等CSSOM构建完成就可以执行JS的内容了

如果不等JS下载解析执行完以后再构建DOM,有可能导致网页的有些内容出现又消失,所以在解析HTML文件的时候,JS代码都会让HTML的解析停止下来,虽然DOM是可以部分解析的,但是对于这个网页来说相当于阻塞看第一次渲染,JS执行完之前什么内容都没有,执行完以后,也就是形成渲染树(构建DOM后),进行布局,最后绘制

现代浏览器会先提前下载script,link,src等标签的资源,不会等解析到标签的时候才下载

即:

  1. CSS不会阻塞DOM解析,但会阻塞DOM渲染

  2. JS阻塞DOM解析,但浏览器会预先下载相关资源

  3. 浏览器遇到scirpt且没有defer或async属性的时,会触发页面渲染,如果前面CSS资源未加载完毕,浏览器会等待加载完成后执行脚本

# CSS和JS引入位置说明

  1. CSS资源尽量放在head部分
  2. JS资源尽量放在body结束标签之前
  3. CSS资源尽量优先于JS资源引入

# 引入位置解释

  1. 因为CSS解析和DOM解析可以同时进行,所以CSS资源放在头部不会影响DOM解析,而且放在头部也会优先开始加载CSS样式,在渲染DOM的时候也已经知道了自己的样式,所以一次就可渲染成功,如果将CSS放在底部,那么会优先渲染DOM,而浏览器为了更好的用户体验,渲染引擎会尝试尽快在屏幕上显示内容,也就是说渲染引擎会边解析、边渲染、边布局显示,已尽快减少白屏时间,所以随着CSS规则树的构建,还需要对之前渲染树重新渲染,可能会导致回流和页面跳动。
  2. JS放在body标签结束之前,首先可以确保能取到需要操作的DOM对象,也可缩短因JS阻塞。而造成的白屏时间,提升用户体验。因为如果把JS放在head部分,JS运行会阻塞DOM树和CSS树构建,导致白屏时间延长,影响用户体验。
  3. 因为JS在运行时,如果需要操作CSS,但该CSS还没有下载和构建,则首先会阻塞JS线程,然后开启新线程去下载解析构建CSS规则树,再执行JS代码