本文会把 dom 的解析,加载,渲染结合 window.performance 一起讲。
dom 的解析
解析:HTMl 解析器把 HTML 构建成 HTML 树形数据结构,也就是 DOM 树。
注意,没有 async 或 defer 标签的 js dom 在加载(拉取并放入内存)和执行时都会阻塞 DOM 树的解析和渲染。
不加 async defer
加 async
加 defer
如何理解 js 阻塞 dom 的解析呢?
dom 解析 -> 碰到 script js 标签 -> dom 停止解析,下载 js 并执行 js -> js 执行完后继续解析 dom
拉取 css (指使用 link 标签,浏览器会单独开启一个下载线程)并不影响 dom 的解析,但是影响 dom 的渲染
dom 的渲染
渲染:dom 渲染指的是 dom 树和 cssom 树生成渲染树,进行布局(计算位置信息和大小)和显示,并把计算结果传给显卡,让显卡绘制界面。
再次强调一遍,css 的拉取和加载并不影响 dom 树的解析,但是会阻塞 dom 树的渲染。
内联,外联的 css 加载都不会阻塞后续的 dom 解析。
内联例子:<div style="background:#f7f7f7;"></div>
外联例子:<link rel="stylesheet" media="screen" type="text/css" href="css/css.css" />
load 事件和 DOMContentLoaded 事件区别
load 事件是指所有内容都已经加载完毕才会触发的事件,包括 dom 加载完毕,资源文件加载完毕。(加载:资源被放入内存)
DOMContentLoaded 事件指的是所有 dom 被加载完毕的时间。
显然,在时间轴上 DOMContentLoaded 要先于 load 事件。
白屏时间
当用户输入完 url 后按下回车,到第一个 dom 元素被展示在页面上的时间。也可以理解为,开始查询 dns 之前 (fetchStart) 到 dom 树已经解析完毕并且刚刚开始渲染的时间 (domInteractive)。可以用 window.performance.timing 计算出这一时间。计算方法为:
let t = window.performance.timing
console.log(t.domInteractive - t.fetchStart)
首屏时间
是指,页面(电脑屏幕大小的页面,不是整个页面)的内容已经完全被加载到浏览器的时间,可以用两种方法去计算,区别不大。
loadEventStart: 开始执行 load 事件中的回调函数的时间
domContentLoadEventEnded: dom 元素和所有资源文件都被加载完毕的时间
let t = window.performance.timing
console.log(t.loadEventStart - t.fetchStart)
console.log(t.domContentLoadEventEnded - t.fetchStart)
解析 dom 树的时间
let t = window.performance.timing
console.log(t.domInteractive - t.domLoading)
渲染 dom 树的时间
let t = window.performance.timing
console.log(t.domComplete - t.domInteractive)
欢迎指正。