网页解析过程:
HTML解析过程
默认情况下服务器给浏览器返回index.html文件,因此解析HTML是所有步骤的开始,解析HTML过程会构建Dom Tree
生成CSS规则
在解析过程中,如果遇到CSS的link元素,会有浏览器下载对应的CSS文件(不会影响DOM)的解析
对CSS下载完成后,会对CSS文件进行解析,解析出规则树,即CSSOM
构建Render Tree
当DOM Tree和CSSOM Tree有了过后就可以两者结合构建Render Tree了
注:link元素不会阻塞DOM Tree的构建,但会阻塞Render Tree的构建
Render Tree和Dom Tree并不是一一对应的关系,对于display为none的元素,不会出现在Render Tree中
布局和绘制
渲染树会显示每个节点的样式,但不会给出每个节点的尺寸和位置,布局就是确定渲染树中每个节点的宽度、高度和位置信息
绘制就是将布局阶段计算的每个frame转为屏幕上实际的像素点,包括将元素的可见部分进行绘制,比如文本、颜色、边框、阴影、替换元素
script元素和页面解析的关系
在HTML解析过程中,遇到script元素是不能继续构建DOM Tree的;会首先下载JavaScript代码,并执行脚本,等脚本执行结束后,继续解析HTML,构建DOM Tree
原因: JavaScript的一个作用是操作DOM,并修改DOM,如果等DOM Tree构建完成后执行JavaScript,会引起严重的回流和重绘,影像性能
但是: 目前的Vue/React开发模式,脚本比HTML页面更重,等到JavaScript解析会造成页面阻塞,在脚本执行完成钱,用户在界面上看不到任何东西
script解析优化:defer、async
defer: 浏览器不需要等到脚本下载,继续解析HTML,构建DOM Tree
不会阻塞DOm Tree的构建,等到DOM Tree构建完成后,在DOMContentLoaded事件之前执行代码
带多个defer的脚本按顺序执行
从某种角度来说,defer可以提高性能,并且推荐放到head元素中
注:defer仅适用于外部脚本,对于script默认内容会忽略
async: 脚本完全独立
浏览器不会因async阻塞
async不能保证不同脚本之间的顺序,独立下载、运行
async不能保证在DOMcontentLoaded之前或之后运行
defer通常用于文档解析后会操作DOM的JavaScript代码,并且对多个script文件有顺序要求的
async通常用于独立的脚本,对其他脚本,DOM没有依赖的