什么是web性能
简单来说就是你的网站够不够快
- 打开速度
- 动画效果
- 表单提交
- 列表滚动
- 页面切换
- 。。。
MDN上的web性能定义:Web性能是网站或应用程序的客观度量和可感知的用户体验
- 减少整体加载时间: 减少文件体积、减少HTTP请求、使用预加载
- 使网站尽快可用:仅加载首屏内容,其它内容根据需要进行懒加载
- 平滑和交互性:使用css替代js动画、减少UI重绘
- 感知表现:你的页面可能不能做得更快,但你可以让用户感觉更快。耗时操作要给用户反馈,比如加载动画、进度条、骨架屏、等提示信息。
- 性能测定:性能指标、性能测试、性能监控持续优化
为什么要关注Web性能
- 用户的留存
- 网站的转化率
- 体验与传播
- 搜索排名
- 客户投诉
- 提升工作效率
- 。。。
如何进行Web性能优化?
- 首先需要了解性能指标 -多快才算快?
- 使用专业的工具可量化地评估出网站或应用的性能表现;
- 然后立足于网站页面响应的生命周期,分析出造成较差性能表现的原因;
- 最后进行技术改造、可行性分析等具体的优化实施;
- 迭代优化
性能指标
- RAIL性能模型
- 基于用户体验的核心指标
- 新一代性能指标:Web Vitals
性能测量
- 浏览器DevTools调试工具 (网络监控分析、性能监控分析...)
- 灯塔(Lighthouse) 网站整体质量评估,并给出优化建议
- WebPageTest (多测试地点、全面的性能报告)
生命周期
优化方案
- 从发出请求到收到响应的优化、比如DNS查询、HTTP长连接、HTTP2、HTTP压缩、HTTP缓存等;
- 关键渲染路径优化,比如是否存在不必要的重绘和回流
- 加载过程的优化,比如延迟加载,是否有不需要在首屏展示的非关键信息,占用了页面加载的时间;
- 资源优化、比如图片、视频等不同格式类型有不同的使用场景,在使用的过程中是否恰当;
- 构建优化,比如压缩合并、基于webpack构建优化方案等。
- ... ...
WEB性能指标
我们已经知道性能的只要性,但当我们谈论性能的时候,让一个网页变得更快,具体是指那些?
事实上性能是相对的:
- 对于一个用户而已,一个站点可能速度很快(在具体功能强大的设备的快速网络上),而对于其他一个用户而言,一个站点可能会慢(在具有低端设备的慢速网络上)
- 两个站点可能会在完全想通的时间内完成加载,但一个站点似乎加载速度会更快(如果它逐步加载内容,而不是等到最后显示任何内容)
- 一个网站可能会出现快速加载但后来(在全部或没有)慢慢地响应用户的交互
LCP: 它测量的是从页面开始加载到页面的 "主要内容 " 完全呈现在屏幕上所需的时间。换句话说,LCP 是测量用户何时看到页面的 "主要内容 " 的指标
FID: 指的是用户首次与网页互动时的延迟时间,更详细的解释是,是从用户首次与网页互动(即,点击链接、点按按钮或使用由 JavaScript 提供支持的自定义控件)到浏览器实际能够开始处理事件处理脚本以响应相应互动的时间。
CLS: (累计布局偏移)衡量的是页面在加载过程中元素意外移动的总量。这会导致糟糕的用户体验,比如用户点击错误的链接或阅读被打断。CLS的目标值是小于0.1,意味着布局偏移较小,用户体验较好。
RAIL性能模型
是以用户为中心,最终目标不是让你的网站在任何特定设备上都能运行很快,而是使用户满意。
- 响应(Response):应该尽可能快速的响应用户,应在100ms以内响应用户输入
- 动画(Animation): 在展示动画的时候,每一帧应该以16ms进行渲染,这样可以保持动画效果的一致性,并且避免卡顿
- 空闲(ldle):当使用javascript主线程的时候,应该把任务划分到执行时间小于50ms的片段中去,这样可以释放线程以进行用户交互
- 加载(Load): 应该在小于1s的时间内加载完成你的网站,并可以进行用户交互;
基于用户体验的性能指标
- First Contentful Paint (FCP): 首次内容绘制,浏览器首次绘制来自DOM的内容的时间,内部必须是文本、图片、非白色的canvas或SVG,包括带有正在加载中的web字体的文字。
- Largest Contentful Paint (Lcp): 最大内容绘制,可视区域中最大的内容元素呈现到屏幕上的时间,用以估算页面的主要内容对用户可见时间
- First input Delay(FID): 首次输入延迟,从用户第一次与页面交互(列如单击链接、点击按钮等)到浏览器实际能够响应应该交互的时间
- Time to Interactive(TTI): 表示网页第一次完全达到可交互状态的时间点,浏览器已经可以持续性的响应用户的输入。完全达到可交互状态的时间点是在最后一个长任务完成的时间,并且在随后的5秒内网络和主线程是空闲
- Total Block Time (TBT): 总阻塞时间,度量了FCP和TTI之间的总时间,在该时间范围内,主线程被阻塞足够长的时间以防止输入响应
- Cumulative Layout Shift (CLS): 累计布局偏移,CLS会测量在页面整个生命周期中发生的每个意外的布局移位的所有单独布局移位分数的总和,它是一种保证页面的视觉稳定性从而提升用户体验的指标方案。
测量Web Vitals
- 性能测试工具,比如Lighthouse
- 使用web-vitals库
- 使用浏览器插件Web vitals
使用Lighthouse测试web性能
使用WebPageTest测试性能
官网:https://www.webpagetest.org/
使用Chrome DevTools测试性能
-
任务管理器查看内存 cpu 进程
-
network
-
Coverage 面板
打开控制台 ctrl + shift + P 在输入coverage 查看每个资源的使用率
-
Memory面板
用来分析内存泄露情况
-
Performace面板
对网站应用的运行时性能表现进行检测与分析,其可检测的内容不仅包括页面的每秒帧数(FPS)、CPU的消耗情况和各种请求的时间花费,还能查看页面在前1ms与后1ms之间网络任务的执行情况等内容。
-
FPS计数器
打开控制台 ctrl+shift + p 输入 fps
请求和响应优化
目的: 更快的内容到达时间
核心思路:
- 更好的连接传输效率
- 更少的请求数量
- 更少的资源大小
- 合适的缓存策略
最大的实践:
- 减少DNS查找:每次主机名的解析都需要一次网络往返,从而增加了请求的延迟时间,同时还还阻塞后续的请求
- 重用TCP连接:尽可能的使用持久链接,以消除因TCP握手和慢启动导致的延迟
- 减少HTTP重定向: HTTP重定向需要额外的DNS查询、TCP握手等非常耗时,最佳的重定向次数为0
- 压缩传输的资源:比如Gzip、图片压缩
- 使用缓存:比如http缓存、CDN缓存、Service Worker缓存
- 使用CDN(内容分发网络):把数据放在离用户地理位置更近的地方,可以明显减少每次TCP连接的网络延迟、增大吞吐量
- 删除没有必要请求的资源
- 在客户端缓存资源:缓存必要的应用资源,避免每次都重复请求想同的内容,列如多图片在下载可以考虑使用缓存。
- 内容在传输前先压缩:传输数据之前应该先压缩应用资源,把要传输的字节减少到最小,在压缩的时候确保对每种不同的资源采用最好的压缩手段
- 消除不必要的请求开销:减少请求的HTTP首部数据(比如Http Cookie)
- 并行处理请求和响应:请求和响应的排队都会导致延迟,可以尝试并行的处理请求和响应(利用多个http1.1连接实现并行下载,在可能的情况下使用http管道计数)。
- 针对协议版本采取优化措施:升级到HTTP2.0
- 根据需要采用服务端渲染方式:这种方式可以解决SPA应用首屏渲染慢的问题
- 采用预渲染的方式快速加载静态页面。页面渲染的极致性能,比较适合静态页面
DNS解析优化
- 减少DNS的请求次数
- 进行DNS预获取: DNS Prefetch
dns-prefetch
dns预获取是尝试在请求资源之前解析域名,可以减少用户等待时间,提示用户体验。
dns-prefetch可帮助开发人员掩盖DNS解析延迟,HTML元素通过dns-prefetch的rel属性值提供此功能。然后在href属性中指要跨域的域名
javascript
<link rel="dns-prefetch" href="" />
- 延长DNS缓存时间
- 尽可能使用A或AAAA记录代替CNAME
- 使用CDN加速域名
- 自己搭建DNS服务
HTTP强制缓存
浏览器判断所请求的目标资源是否有效,直接从强制缓存中返回请求响应,无须与服务器进行任何通信。
通过expires 与cache-control字段
协商缓存
使用本地缓存之前,需要向服务器发起一次get请求,与之协商当前浏览器保存的本地缓存是否已经过期。
基于last-modified 和 ETag
使用requestAnimationFrame实现动画效果
requestAnimationFrame 会在浏览器的每次重绘之前执行回调函数,确保动画和屏幕刷新同步,从而提升动画的流畅度和性能。
javascript
function animate() {
// 在此处进行动画更新操作
console.log('Animating...');
// 请求下一帧动画
requestAnimationFrame(animate);
}
// 启动动画
requestAnimationFrame(animate);
使用WebWorker线程执行代码任务
Web Worker创建的一些辅助线程,分别去帮主线程分担一些复杂的、耗时的js运算,这样的话,主线程后续的代码执行就不会阻塞,当辅助线程计算出复杂耗时运算结果后,再与主线程通信,将计算出的结果告知主线程。
Web Worker新技术价值,简而言之:提升前端代码运算执行效率