如何以低性能损耗、高准确度测量首屏完全加载指标?
首屏完全加载时间的高效测量方案
核心需求回顾
需要测量满足以下任一条件的最早时间:
要么body高度大于视口高度,要么文档加载完成
优化方案:结合ResizeObserver与关键DOM事件
针对之前两种方案的缺陷,我们可以通过以下方式平衡性能与准确性:
用ResizeObserver替代MutationObserver
ResizeObserver专门用于监听元素尺寸变化,只会在body高度发生改变时触发回调,相比监听整个DOM子树的MutationObserver,性能开销大幅降低,完全适配流式HTML分块的场景。结合文档加载事件兜底
同时监听DOMContentLoaded和load事件,覆盖文档加载完成的场景,避免因body高度始终小于视口导致无法触发ResizeObserver的情况。单次触发后立即终止监听
一旦满足条件,立即停止所有监听和检测逻辑,避免后续不必要的性能消耗。
具体实现代码
function measureFirstScreenComplete() { return new Promise((resolve) => { let resolved = false; // 核心检查逻辑 const checkCondition = () => { if (resolved) return; const bodyHeight = document.body?.clientHeight || 0; const viewportHeight = window.innerHeight; if (bodyHeight > viewportHeight || document.readyState === 'complete') { resolved = true; // 记录当前精确时间戳 resolve(performance.now()); // 停止所有监听 resizeObserver.disconnect(); window.removeEventListener('DOMContentLoaded', checkCondition); window.removeEventListener('load', checkCondition); } }; // 初始化ResizeObserver监听body高度变化 const resizeObserver = new ResizeObserver(checkCondition); if (document.body) { resizeObserver.observe(document.body); } else { // 若body未初始化,等待DOM加载后启动监听 window.addEventListener('DOMContentLoaded', () => { resizeObserver.observe(document.body); }); } // 监听文档加载事件,兜底处理 window.addEventListener('DOMContentLoaded', checkCondition); window.addEventListener('load', checkCondition); // 初始检查一次,覆盖页面已加载完成的场景 checkCondition(); }); } // 使用示例 measureFirstScreenComplete().then(time => { console.log('首屏完全加载时间:', time); });
关键优势
- 低性能开销:ResizeObserver仅在元素尺寸变化时触发,不会因流式HTML的频繁DOM变更产生大量回调
- 高准确性:避免了定时器的间隔误差,同时通过事件监听覆盖所有边界场景
- 自动终止:满足条件后立即停止所有监听,无后续性能损耗
内容的提问来源于stack exchange,提问作者avdotion
相关产品推荐
相关产品推荐

