前端性能优化实战
为什么要进行性能优化?
1、用户的留存率:根据Google营销平台提供的调研发现,如果网站页面的加载时间超过3s,就会有53%的移动网站的访问遭到用户抛弃。
2、网站的转化率:从运营角度来看,网站转化率是一个非常重要的考量指标,网站转化率指的是用户进行了某项目标行为的访问次数与总访问才次数的比率。
因此,从用户使用角度来看有以下几点能感知网站的性能:
1、响应:必须在100ms内收到反馈,如果超过100ms的时间,用户就会感知到延迟;
2、动画:由于视神经存在反应速度造成,其值是1/24s,即当我们所见的物体移除后,该物体在我们眼中并不会立即小时,会延续存在1/24s的时间;
3、空闲:利用空闲时间处理延迟,可减少预加载的数据大小,以保证网站/应用快速完成加载;处理任务按50ms为单位分组,保证用户在发生操作后100ms内给出响应;
4、加载:用户感知要求我们尽量在1s内完成页面加载,如果没有完成,用户的注意力就会分散到其他事情上,并对当前处理的任务产生中断感(在1s内完成加载并渲染出页面的要求,并非要完成所有页面资源的加载),从用户感知体验的角度来说,只要关键渲染路径完成,用户就会认为全部加载已完成。
常用的前端性能检测工具以及指标
检测工具:
1、chrome任务管理器:查看所有进程的关于GPU、网络和内存空间的使用情况;
2、chrome的Network面板:查看网站所有资源的请求情况,包括加载时间、尺寸大小、优先级设置及HTTP缓存触发情况等信息;
3、chrome的Coverage面板:通过它监控并统计出网站应用运行过程中代码执行的覆盖率(统计结果包括米格文件字节大小、执行过程中已覆盖的代码字节数以及可视化覆盖率条形图);
4、chrome的Memory面板:可以快速生成当前的堆内存快照,或者查看内存随时间的变化情况;
5、chrome的Performance面板:启动监控功能后,与网站页面的任何交互所引发的资源请求、页面渲染、函数执行及GPU耗时等信息,都会按照时间线的维度记录下来;
6、chrome的Performance monitor面板:可以实时监控网站应用运行过程中的CPU占用率、JavaScript内存使用大小、内存中挂的DOM节点数、JS事件监听次数及页面发生重绘与重排的处理时间;
7、PageSpeed Insights:检测网站页面加载性能的自动化工具,能够针对移动设备和桌面设备分别进行检测并生成相应的优化报告;
8、webpagetest网站分析工具:对检测分析的环境配置进行高度自定义,内容包括测试节点的物理位置、设备型号、浏览器版本、网络条件和检测次数等,除此之外还提供目标网站应用于竞品之间的性能比较,以及查看网络路由情况等多种维度下的测试工具。
9、chrome的Lighthouse(灯塔):通过监控和检测网站应用的各方面性能表现,为开发者提供优化用户体验和网站性能的知道建议。
10、chrome的Audits面板:将lighthouse集成到了Audits面板中(目前还处于Beta版本阶段),广告性能评估项,主要为了帮助提升广告的加载速度和总体质量。
首屏构建指标:
- FP(First Paint):首次绘制时间,也就是白屏,这个指标用于记录页面第一次绘制像素的时间,从页面开始加载到浏览器中检测到渲染(任何渲染)时被触发(例如背景改变,样式应用等)【计算方式:白屏时间 = firstPaint - pageStartTime】;
- FCP(First Contentful Paint):首次内容绘制时间,也是首屏,这个指标用于记录页面首次绘制文本、图片、非空白 Canvas 或 SVG 的时间,从页面开始加载到页面内容的任何部分呈现在屏幕上的时间【计算方式:首屏时间 = firstContentTime - pageStarTime】。
- FMP(First Meaningful Paint):首次有意义的渲染帧,也是首次有效绘制,从页面加载开始,到大部分或者主要内容已经在首屏上渲染的时间点, 表示页面的“主要内容” 开始出现在屏幕上的时间点,这项指标因页面逻辑而异,因此上不存在任何规范(只是记录了加载体验的最开始。如果页面显示的是启动图片或者loading 动画,这个时刻对用用户而言没有意义);
- LCP(Largest Contentful Paint):最大内容绘制时间,用于记录视窗内最大的元素绘制的时间,该时间会随着页面渲染变化而变化,因为页面中的最大元素在渲染过程中可能会发生改变,另外该指标会在用户第一次交互后停止记录,指标代表的是视窗最大可见图片或者文本块的渲染时间 (可以帮助我们捕获更多的首次渲染之后的加载性能,但这各指标过于复杂,而且很难解释,也经常出错,没办法确定主要内容什么时候加载完)【
<img>
元素、<svg>
中的<imge>
元素、<video>
元素(如果定义了封面图,会影响LCP)、带url()背景图的元素、块级元素有文本节点或者内联文本子元素】。 - CLS(Cumulative Layout Shift):累计位移偏移,记录了页面上非预期的位移波动。计算方式为:位移影响的面积 * 位移距离。
- LT(Long Task):当一个任务执行时间超过50ms 时消耗到的任务(50ms 阈值是从RAIL模型总结出来的结论,这个是google研究用户感知得出的结论,类似永华的感知/耐心的阈值,超过这个阈值的任务,用户会感知到页面的卡顿);
- TTI(Time to Interactive):首次可交互时间。这个指标计算过程略微复杂,从页面开始到它的主要子资源加载到能够快速地响应用户输入的时间。(没有耗时长任务),它需要满足以下几个条件:
- 从 FCP 指标后开始计算;
- 持续 5 秒内无长任务(执行时间超过 50 ms)且无两个以上正在进行中的 GET 请求;
- 向后搜索静默窗口前的最后一个长任务,如果没有找到长任务,则在FCP上停止;
- TTI 是在安静窗口之前最后一个长任务的结束时间(如果没有找到长任务,则与FCP相同)。
- FID(First Input Delay):首次输入延迟时间,记录在 FCP 和 TTI 之间用户首次与页面交互时响应的延迟,从用户第一次与页面交互到浏览器实际能够开始处理事件的时间。(点击,输入,按键),(人为因素会干预TTI 的结果强调了第一印象,而第一印象对于塑造我们对网站质量和可靠性的整体印象至关重要,因此,改善网站的第一个用户交互将对提高整体的网络交互性产生最大的影响);
- TBT(Total Blocking Time):阻塞总时间,记录在 FCP 到 TTI 之间所有长任务的阻塞时间总和(FID需要依赖用户实际进行操作来计算,不方便开发者通过工具进行测量);
- DCL(DOMContentLoaded):DOM解析完毕,当HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,无需等待样式,图像和子框架的完成加载;
- Load(Onload Event):它代表页面中依赖的所有资源加载完的事件;
常用过程指标:
- DOMReady:也就是DOMContentLoad,在Network面板中底部就能看到;
- TTFB(Time To First Byte):是指客户端从发起请求到接收到服务器相应的第一个字节的时间,是反映网站性能的重要指标,静态页面一般在50ms是非常理想的值 ;
- Load:页面资源完全加载好的时间点;
- RTT(Round-Trip Time):往返时延,从发送端发送数据开始,到发送端接收到来自接收端的确认时间,即一来一回的时间,一般来说这个时间由物理距离、网络传输路径等决定,确定RTT的时间,最简单的方式就是Ping一下,在Ping的时候可以看到time=xxms大致就是1个RTT ;
网站具体性能优化方向和优化点
1、服务器优化:增加缓存(协商缓存和强缓存);
2、图像优化:根本思想是压缩;
- 图像压缩:根据业务选择有损压缩和无损压缩;
- 图像格式:图像格式选择依次为:矢量图(SVG)=> WebP => JPEG => PNG8 => PNG8,如果存在动画的话选择GIF;
- CSS Sprite(雪碧图):通过多张小图标拼接成一张大图,有效地减少HTTP请求数量;增加如何开发。
- display:none:浏览器部分会加载图像,如果不清楚会不会加载未显示的图像,推荐使用picture或img srcset进行响应式显示;
3、Web字体:常用的字体格式有EOT、TTF、WOFF和WOFF2;项目一般会通过@font-face声明字体系列,可以通过对字体资源进行预加载(<link rel="preload">
)
4、资源加载
- 图像延时加载:Intersection Observer方式、CSS类名方式(通过background-image实现)、原生的延迟加载支持(
<img>
、<iframe>
标签的loading属性原生支持延迟加载,loading包含lazy、eager、auto值) - 视频加载:chrome会对视频资源进行预加载(在html完成加载和解析时触发DOMContentLoaded事件开始请求视频资源);尺寸过大的GIF动画使用视频代替(video使用属性autoplay、muted、loop、playsinline);基于Intersection Observer用Js实现对延迟加载的控制;
5、首屏加载:在延迟加载的媒体资源到达首屏边界之前设置一个缓冲区,以便媒体资源在进入视窗之前就开始加载(Intersection Observer,通过rootMargin属性来建立缓冲);资源占位(LQIP或SQIP或Base64图片等,资源错误时显示错误的提示信息);渐进式显示JQPEG图像(采用Image.decode()方法进行一步图像解码);
6、资源优先级:对资源重要性进行判断划分优先级;预加载(<link ref="preload">
);预链接(<link ref="preconnect" href="xxx">
);预提取(<link rel="prefetch" href="xxx">
);
7、构建优化
- 压缩与合并:HTML压缩(node的html-minifier插件)、CSS压缩(clean-css插件)、JavaScript(压缩uglify-js插件、gulp的gulp-concat合并插件或者webpack的entry和output配置、uglifyjs-webpack-plugin);
- 多进程打包:happypack多线程插件;
- 可视化分析:webpack-bundle-analyzer分析插件;
8、CSS样式优化:CSS引擎查找样式表规则匹配顺序从右向左,使用BEN规范(中画线-单下划线_双下划线__);
9、搜索引擎优化:meta的title、description、keywords;img的alt;使用语义化标签;
10、缓存:HTTP缓存(设置cache-control属性值no-store禁止缓存、协商缓存no-cache、服务器代理缓存public和private设置ETag或last-modified)、Service Worker缓存、Push缓存、CDN缓存;
11、数据存储:保存登录状态的Cookie(同步存取)、浏览器本地存储LocalStorage和SessionStorage(同步存取)、客户端数据持久化存储方案WebSql和Indexed DB(异步存取)、直接存储在本机的文件系统上(异步存取)。
12、TTFB优化:减少请求的传输量、减少服务端的处理时间(优化处理逻辑,增加缓存、优化慢SQL;使用流式渲染,先返回可渲染的内容,再流式地返回更多耗时的内容【在Response Header中,增加Transfor-Encoding:chunked,告知浏览器HTML将会被一块一块地流式返回,Facebook构建了bigpipe 】)、增加离客户更近的服务器节点(CDN)、减少RTT(物理距离缩短就能相应减少时间、preconnect、复用连接、域名收拢(解决加载阻塞问题)、TCP Fast Open、QUIC和HTTP/3 )、重定向逻辑前置(合并重定向);
13、HTTPS协议优化: 确保证书链完整、启用TLS 1.3 、不滥用EV证书、开启OSCP Stapling(开启OSCP验证) 等;
附录:
《Web前端性能优化》
《前端性能揭秘》