Open goldEli opened 5 years ago
<script>
var startTime = new Date().getTime()
for (let i = 0; i < 100000; ++i) {
const li = document.createElement('li')
li.textContent = "This is li" + i
document.body.append(li)
}
// js 执行时间
const excuteTime = new Date().getTime() - startTime
console.log(excuteTime)
// 渲染时间
setTimeout(() => {
const renderTime = new Date().getTime() - startTime - excuteTime
console.log(renderTime)
}, 0)
</script>
如上代码,末尾通过 setTimeout 就可以打印出渲染时间。
为什么呢?
也就是说当 JavaScript 代码在执行时,渲染就会停止,渲染的时候,代码执行就会停止。
试想一下如果不互斥,那么 JavaScript 代码在操作 DOM 的同时渲染进程又在渲染页面,那么结果是无法预期的
每个执行栈执行的内容被称为宏任务,当执行栈执行完毕,即宏任务结束,渲染进程开始渲染。
以上面的代码为例,第一个宏任务的执行栈中有 setTimeout,那么它的回调就是第二个宏任务,所以在渲染结束后,执行 setTimeout 的回调就能计算出渲染时间。
如果把 setTimeout 改成 Promise.then
也可以实现吗?
不能。
Promise.then
属于微任务,一个宏任务执行完毕后需要执行完微任务队列的所有内容才开始渲染。
如下图:
导航定时可以很容易地测量网站的实际速度和性能,并找到需要调优的问题区域。例如,导航计时可以帮助您精确地监视客户页面导航并跟踪用户活动的计时,从而帮助您定位延迟问题。然后,您可以更容易地确定性能瓶颈,并找到有效的解决方案来减少延迟,提高网站的速度和效率。旧的性能度量系统不能提供导航定时所支持的完整的端到端延迟图。
performance api有如下属性:
属性 | 简介 |
---|---|
connectEnd | Time when server connection is finished. |
connectStart | Time just before server connection begins. |
domComplete | Time just before document readiness completes. |
domContentLoadedEventEnd |
Time after DOMContentLoaded event completes . |
domContentLoadedEventStart | Time just before DOMContentLoaded starts. |
domInteractive | Time just before readiness set to interactive. |
domLoading | Time just before readiness set to loading. |
domainLookupEnd | Time after domain name lookup. |
domainLookupStart | Time just before domain name lookup. |
fetchStart | Time when the resource starts being fetched. |
loadEventEnd |
Time when the load event is complete . |
loadEventStart | Time just before the load event is fired. |
navigationStart |
Time after the previous document begins unload . |
redirectCount | Number of redirects since the last non-redirect. |
redirectEnd | Time after last redirect response ends. |
redirectStart | Time of fetch that initiated a redirect. |
requestStart | Time just before a server request. |
responseEnd | Time after the end of a response or connection. |
responseStart | Time just before the start of a response. |
timing | Reference to a performance timing object. |
navigation | Reference to performance navigation object. |
performance | Reference to performance object for a window. |
type | Type of the last non-redirect navigation event. |
unloadEventEnd | Time after the previous document is unloaded. |
unloadEventStart | Time just before the unload event is fired. |
计算页面渲染时间,我们需要使用三个属性:
所以我们想要获得页面dom树加载时间和完整页面加载时间:
window.onload = function () {
var DomloadTime = window.performance.timing.domContentLoadedEventEnd-window.performance.timing.navigationStart;
var PageloadTime = performance.now();
console.log('Dom load time is ',DomloadTime, PageloadTime);
}
可见 页面完全加载会比dom树加载慢一些。
navigationStart:从同一个浏览器上下文的上一个文档卸载(unload)结束时的UNIX时间戳。如果没有上一个文档,这个值会和PerformanceTiming.fetchStart相同
domComplete:文档解析完成(理解为 dom 解析完成 + render tree 生成完成)
const { navigationStart, domComplete } = performance.timing; DomloadTime = domComplete - navigationStart
第一个
console
打印出了 js 代码的执行时间。 那如何获取页面渲染的时间呢?