渲染机制概述
解析 HTML 标签, 构建 DOM 树
解析 CSS 标签, 构建 CSSOM 树
把 DOM 和 CSSOM 组合成 渲染树 (render tree)
在渲染树的基础上进行布局, 计算每个节点的几何结构
把每个节点绘制到屏幕上 (painting)
过程分析
拿到HTML代码后,浏览器开始解析HTML代码构建DOM树。
这个过程是根据代码自上而下的。
当解析到style 或者 link外链css时,会阻塞停止HTML的解析,DOM树的构建。
等请求下载解析css并且CSSOM构建完毕时,才会继续解析后面的HTML代码。
当继续解析到script 或者 外链js脚本时,会阻塞停止HTML的解析,DOM树的构建。
注意:
然后继续解析HTML。每解析完一个DOM 就结合CSSOM 绘制好(不同浏览器处理方式不同)。
遇到图片src就建立请求获取图片,但是不等待继续解析后面的HTML(异步并行过程),等到图片获取到以后再回头Reflow,如果没有影响布局则Repaint。
(1)Reflow(回流):浏览器要花时间去渲染,当它发现了某个部分发生了变化影响了布局,那就需要倒回去重新渲染。
(2)Repaint(重绘):如果只是改变了某个元素的背景颜色,文字颜色等,不影响元素周围或内部布局的属性,将只会引起浏览器的repaint,重画某一部分。
等到所有标签解析完毕则渲染结束。
提高网页加载速度 和避免异常情况的处理方法
CSS
为了提高网页加载速度,对于首页无关的样式,需要使用适当的方式避免其阻塞初次渲染:
- 使用media=print媒体查询,虽然加载样式表,但只针对打印时才应用该样式,不会阻塞初次渲染。
- 通过DOMAPI引入CSS,可以避免阻塞。
- CSS中<link rel="preload" href="index_print.css" as="style" onload="this.rel='stylesheet'">。
另:css选择器的机制是从右往左,所以应避免过多的选择器嵌套
JS
JS脚本执行会阻塞HTML Parser;
CSS解析会阻塞JS脚本执行:js可能会读、写CSSOM
虽然JS会阻塞HTML Parser解析;但是浏览器的资源异步加载机制Preload会异步加载head标签内的资源
非关键JS资源解析阻塞的优化方案:
- 将JS资源文件放在文档底部,延迟JS的执行(但是存在必须解析完HTML才能加载JS资源,相较于head标签中加载会慢)
- 使用defer延迟脚本执行:scipt标签的defer属性,脚本会在HTML文档解析完毕后再开始执行;被defer的脚本在执行时严格按照HTML文档中出现的顺序执行---优势可以提早加载JS资源,但是解析完HTML再执行
- 使用async异步执行脚本:
-当script标签有async属性时,脚本执行不会阻塞HTML Parser,只要脚本加载完毕便开始执行
被async的脚本,不会严格按照在HTML文档中的顺序执行
async适用于无依赖的外部独立资源(注意不要错误操作状态)
font
img
图片资源的加载不会阻塞渲染,但是最好在HTML标签中设置图片的高度和宽度,可以在Layout时留出图片渲染的空间,避免页面的抖动