浏览器渲染机制
主要过程为:
- 解析HTML并构建DOM树
- 解析CSS并构建CSSDOM树
- 将DOM和CSSDOM合并成渲染(render)树
- 根据渲染树布局,计算每个节点的位置
- 将各个节点绘制到屏幕上
阻塞机制
CSS
- style标签会阻塞HTML的解析,直至生成CSSDOM后才会继续解析
- link标签引入的外部资源,资源下载不会阻塞HTML解析,会阻塞之后的渲染
- link标签引入的外部资源,资源下载不会阻塞js的加载,会阻塞js的执行(这里的js是同步的)
js
- js的加载和执行都会阻塞HTML的解析
防阻塞机制
CSS
- 可以使用媒体类型和媒体查询解除对渲染的阻塞
<link href="index.css" rel="stylesheet">
<link href="print.css" rel="stylesheet" media="print">
<link href="other.css" rel="stylesheet" media="(min-width: 30em) and (orientation: landscape)">
js
defer
- defer会延迟执行js,使得js加载时不会阻塞HTML的解析
- defer不会改变script代码的执行顺序
- defer在HTML解析完成后执行,执行完成后才会触发DOMContentLoaded
async
- async会异步执行js,如果加载完毕会立即执行。不会按照顺序执行。
- async可能会在DOMContentLoaded 事件之前或之后执行,但是一定会在load触发之前执行
document.createElement
- 动态创建的script默认是异步的(async:true),所以不会阻塞页面
- 动态创建的link标签不会阻塞之后的js的加载和执行
preload 和 prefetch
- preload 可以强制浏览器请求资源,同时不阻塞文档onload事件
- prefetch提示浏览器这个资源将来可能需要,但是把决定是否和什么时间加载这个资源的决定权交给浏览器
- 具体可看:medium.com/reloading/p…
渲染时机
浏览器渲染页面并不一定是解析完HTML之后才会渲染,也可能才解析了一部分。那么它的首次渲染时机是什么?根据上面的分析,总结如下:
- 若head标签里面有同步的css,那么即使已经生成了DOM,也一定会等待css下载并执行完之后才会开始渲染
- 若head标签里面有同步的js,那么会直接阻塞,等待它下载执行完后才会向后执行
- 若script标签在body里面,若正在下载资源,此时HTML解析被阻塞,并且满足上面的两个条件,并且js引擎线程也空闲,则会进行渲染。