首先,defer和async是script标签的两个属性,用于控制js的加载方式,二者都是控制以异步的方式来加载js,不会阻塞DOM树的解析和渲染。
不同点如下:
- defer,在DOM解析完成之后,DOMContentLoaded事件触发之前执行,如果有多个,按顺序执行
- async,在js加载完成之后立刻执行,如果有多个,不能保证执行顺序,先下载完成的先执行,在loaded事件触发之前执行,不能确定和DOMContentLoaded事件触发的时间顺序。
页面渲染过程如下:
- 浏览器一边下载一边解析html文本,构建DOM树;
- 解析到有外部资源,则交给网络线程去下载,如果是外联css资源则不会直接阻塞解析和构建DOM树,如果是外联js且没有defer和async属性,则会阻塞解析和构建DOM树,直到js下载和执行完毕之后才接着解析和构建DOM树。
- 在外联js阻塞时,浏览器会开启一个轻量级线程继续扫描,如果有外部链接,则提前下载。
- 若碰到内联的css,直接解析,构建CSSOM,解析css不阻塞构建DOM树
- 若碰到内联js,先执行,后构建DOM
- js执行前若有css未下载完成,则会阻塞js执行,从而阻塞DOM树构建
- CSSOM和DOM构建渲染树
- 计算布局
- 分层、绘制
渲染的过程是流水线式的,并不是一步全部执行完成之后再执行下一步。