前言
最近在做一些性能优化相干的工作,置信大家在工作过程中也会遇到一些性能优化相干的场景,这对于前端开发者来讲是一项加分技能。为了咱们的用户在应用咱们的产品时可能有一个十分好的体验,咱们须要对页面进行诊断优化。在行业中,咱们的页面P90在两秒内算是达标,超过这个工夫那么你就可能会散失局部用户。
TIP:P90指的是页面性能数据从小到大排序,在90%地位的数据。
比方:P90为两秒,那它的意思就是90%的用户都可能在两秒内关上页面
对于性能优化内容可能比拟多,咱们这里就先着重理解window.onload
相干内容。对于页面加载时长,咱们就防止不了波及window.onload
。
性能剖析
做性能优化必定免不了须要对页面性能进行剖析,咱们个别会应用ChromeDevTool
作为根底的性能剖析工具,察看页面性能状况
Network:察看网络资源加载耗时及程序
Performace:察看页面渲染体现及JS执行状况
Lighthouse:对网站进行整体评分,找出可优化项
明天咱们先着重来看Network
的相干内容,比方咱们关上浏览器控制台:
这里咱们能够看到这两项数据:DOMContentLoaded
工夫为841ms、Load
工夫为2.06s
它俩别离对应两个事件:
DOMContentLoaded
当初始的 HTML 文档被齐全加载和解析实现之后,DOMContentLoaded
事件被触发,而无需期待样式表、图像和子框架的齐全加载。
Load
load
事件在整个页面及所有依赖资源如样式表和图片都已实现加载时触发。它与DOMContentLoaded
不同,后者只有页面 DOM 加载实现就触发,无需期待依赖资源的加载。
看完两者的解释之后,置信大家应该明确了为什么Load
花的工夫要比DOMContentLoaded
长了吧
因为load
事件会被大量媒体资源阻塞,浏览器只有在它认为页面上的所有资源都加载实现了才会触发load
事件。
两者的区别
DOM残缺的解析过程:
- 解析HTML
- 加载内部脚本与款式文件
- 解析并执行脚本
- DOM树构建(DOMContentLoaded事件触发)
- 加载图片等资源
- 页面加载结束(Load事件触发)
- DOM的解析受JS加载和执行的影响,咱们在优化时应尽量对JS进行压缩、拆分解决(HTTP2下),能缩小
DOMContentLoaded
工夫 - 图片、视频、CSS等资源,会阻塞 onload 事件的触发,咱们在优化过程中须要优化资源的加载机会,让
load
事件尽快触发
深刻了解window.onload
onload触发机会
JS 加载并执行结束且页面中所有外链资源加载实现之后大概 3 - 4ms(这个值跟机型和浏览器无关)
比方:
window.onload = () => { console.log('load')}setTimeout(() => { console.log('timeout')}, 3)
后果是setTimeout
先执行,这里把值改的稍大一点你会发现就是load
先执行了
哪些因素会影响window.onload
JS执行
window.onload = () => { console.log('load')}for(let i = 0; i < 100000; i++) { console.log(i)}
当咱们写了一个十分耗时的JS工作时,你会发现DOMContentLoaded
与Load
事件都会等很久才会触发。
阐明JS的执行不仅会阻塞DOMContentLoaded
事件的触发,也会阻塞Load
事件的触发。所以在优化过程中,JS也是一个重点关注对象。
async异步加载脚本
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.47/vue.cjs.js" async></script><script src="https://cdn.bootcdn.net/ajax/libs/Chart.js/4.2.1/chart.js"></script>
为了比照,这里我加载了两个JS文件,一个应用async
异步加载,一个间接加载,咱们再到控制台来查看此时的加载状况。
这里咱们能够看到两个文件都是在Load
之前就会加载,只不过应用了async
异步加载会比失常加载的后加载,阐明应用了async
异步加载脚本仍然会阻塞Load
的触发。
对于async
的解释MDN上是这样说的:
对于一般脚本,如果存在
async
属性,那么一般脚本会被并行申请,并尽快解析和执行。对于模块脚本,如果存在
async
属性,那么脚本及其所有依赖都会在延缓队列中执行,因而它们会被并行申请,并尽快解析和执行。该属性可能打消解析阻塞的 Javascript。解析阻塞的 Javascript 会导致浏览器必须加载并且执行脚本,之后能力持续解析。
这里可能会有误会,我感觉它应该是不会阻塞其它脚本内容的加载与执行,因为它的加载是在load
之前的,所以它仍然会阻塞load
的触发,但从整体上来看,它对性能优化还是有帮忙的。
defer异步加载脚本
这里还是跟下面一样的场景,咱们把async
换成defer
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.47/vue.cjs.js" defer></script><script src="https://cdn.bootcdn.net/ajax/libs/Chart.js/4.2.1/chart.js"></script>
这里看上去跟async
的加载没什么不同,它的加载仍然会比失常加载的形式滞后,但会在load
之前。
对于defer
:
这个布尔属性的设置是为了向浏览器表明,该脚本是要在文档被解析后,但在触发
DOMContentLoaded
事件之前执行的。蕴含
defer
属性的脚本将阻塞DOMContentLoaded
事件触发,直到脚本实现加载并执行。蕴含
defer
属性的脚本会依照它们呈现在文档中的程序执行。这个属性可能打消阻塞解析的 JavaScript,在这种状况下,浏览器必须在持续解析之前加载和执行脚本。
所以这里跟下面差不多,对性能优化也是有帮忙的,须要留神应用场景。
图片预加载
在工作过程中咱们可能会有一些图片预加载的应用场景,次要是为了可能让一些较大的图片资源可能疾速的渲染出现给用户,咱们个别会提前加载一次图片,等到真正应用时浏览器就能够间接从缓存中取出并渲染。
<div class="container"> <img src="https://imgservices.image.com/s06012023/9ac85415.g0q5wz.png" class="zan_icon" /></div><script> window.onload = () => { console.log('load') } const img = new Image(); img.src = 'https://router.vuejs.org/logo.svg';</script>
比方这里,咱们在html外面通过img
加载了一张图片,在JS中预加载了一张图片,尽管这张图片并没有实在渲染,但它也是会发动申请的,并影响load
事件的触发。
所以咱们在做预加载时也须要思考给页面性能带来的影响
影响load
工夫执行的内容还有很多,在对页面进行性能优化时,这些内容都是能够进行优化方向
onload与native
咱们都晓得H5页面在通过native得webview容器进行渲染时,顶部都会有一个加载进度条,有时候在弱网环境下,这个进度条会始终在那缓缓加载,很长时间不会隐没,十分影响用户体验,这最次要的起因是onload
的触发被阻塞,从而客户端管制的进度条不会隐没,页面调用客户端的办法不会执行。
iOS 中判断 webview 加载实现的 webViewDidFinishLoad 办法,Android 中判断 webview
加载实现的 onPageFinished 办法实质触发机会上都对应页面上的 window.onload
,一般来说会稍晚于 window.onload
(某些非凡状况会早于 window.onload
,比方页面里有 iframe
等状况)。
也就是说 对 onload 有影响的因素也同样会影响这些 Native 办法。而在 Hybrid 开发中,一些 Native 和 Web 之间的交互和调用往往要在webViewDidFinishLoad / onPageFinished
之后。因而如果 onload
的触发被推延了,那么这些 Native
相干的调用也都会被推延。
因而如果是Hybrid利用,尤其要留神让onload尽快触发。
performance性能统计
DOMContentLoaded
事件与Load
事件破费的工夫,咱们能够通过performance
这个对象的一些属性进行统计,工夫准确到纳秒级。很多公司的性能监控平台也次要是利用这个对象的数据进行上报的。
- connectStart:HTTP(TCP)开始建设连贯的工夫。如果是长久连贯,则和 fetchStart 的工夫相等,留神,如果在传输层产生了谬误且从新建设连贯,这里显示的是新建设连贯的开始工夫。
- connectEnd: 实现建设连贯的工夫。
- domComplete:DOM 树解析实现,并且资源准备就绪的工夫,Document.readyState 变为 complete,并将抛出 readystatechange 相干事件。
- domContentLoadedEventEnd:DOM 解析实现后,网页内资源加载实现的工夫(如 JS、css 加载执行结束)。
- domContentLoadedEventStart:DOM 解析实现后,网页内资源加载开始的工夫在 DOMContentLoaded 事件抛出前产生。
- loadEventStart:load 事件触发,也即 load 回调函数开始执行的工夫。留神:如果没有绑定 load 事件,值为 0。
- loadEventEnd:load 事件的回调函数执行结束的工夫。
- 等...更具体内容可查看MDN文档
如果这篇文章有帮忙到你,❤️关注+点赞❤️激励一下作者,关注 前端南玖
第一工夫获取最新文章~