页面性能的影响
性能非常重要,而具体反映到我们的业务场景中,可能会有如下影响:
- 不利于用户留存
- 站点页面的展现速度非常影响用户体验,很多用户会因等待的不耐而放弃站点。
- 研究表明,47 % 的消费者希望页面能够在 2s 内打开。
移动端的页面应该在 3 秒钟内完成加载,若超过这个时间,53% 的用户会直接关闭页面。
- 不利于 SEO
- 谷歌搜索结果中,会给加载速度慢的页面一个较后的排名。
- 不利于产品信息分发
- 用户的空闲总时长是有限的,当花费更多的时间等待页面加载,
则用于消费价值信息的时间就会减少,从而信息消费量也会大幅减少。
- 用户的空闲总时长是有限的,当花费更多的时间等待页面加载,
- 其他等等
- 79% 的消费者在电商站点性能体验较差的情况下,不会再次访问这个站点。
如何优化
- 第一位不是具体手段,而是先收集数据
- 收集数据之前需要了解页面从加载到呈现的步骤(越详细越好)
- 有了数据可以很清晰的了解我们的短板
- 如果不确定哪里是短板可以参考别家的数据
- 结合我们的产品形态制定目标和基准
- 根据目标“寻找”具体手段进行“优化”
如何分析
Analyzing Critical Rendering Path Performance
分析 关键 渲染 路径 性能
performance
- 总概念
- 蓝色(Loading):网络通信和HTML解析
- 黄色(Scripting):JavaScript执行
- 紫色(Rendering):样式计算和布局,即重排
- 绿色(Painting):重绘
- 灰色(other):其它事件花费的时间
- 白色(Idle):空闲时间
关键资源分析
这么多指标,我们应该分析那个呢
1、减少网络请求
HTTP2多路复用 长链接 多资源并行请求 header压缩 body压缩 server主动推送
HTTP1 6个并发限制 雪碧图
2、提高打包速度
- 减少打包体积
重复依赖引用重复打包,代码压缩 - code split 优化首次加载 按需加载 懒加载
- bundle split分包 合理分包,充分利用缓存
- 第三方依赖external 减少整体打包编译时间和体积
- 不适用场景
- 需要按需引入的 npm 包, 对于按需加载的包没必要用 cdn 全量引入。
- cdn 引入的形式可能会造成全局污染问题,可根据项目实际情况适用。
- 对于体积比较大且不是首屏用到的包,用 cdn 形式引入,可能会影响首屏加载速度。
nextjs/image图片解决方案
- 图片流量优化,通过格式自适应和分辨率自适应以达到提升站点性能并节省流量的目的;
- 提升视觉稳定性,内置四种图片布局方式,涵盖绝大多数的图片渲染场景,避免累积布局偏移 CLS;
- 更快的页面加载速度,支持过渡图占位+图片懒加载;
- 可灵活处理图片资源,支持图片缩放、压缩、格式转换等能力
目标
因此,我们面向 Web 开发者提供了一套图片优化方案,核心目标包括:
- 降低流量成本:通过图片压缩,分辨率自适应,应用 WebP、AVIF 等高压缩率图片格式,
减小图片体积,降低站点 CDN 成本,同时也提升图片加载速度; - 提升图片用户体验:建立 Web 图片评估体系,支持对站点图片体验做出评估并给出优化建议,
在减小图片体积的基础上,通过懒加载、图片预占位、稳定性布局等手段提升图片加载的流畅性; - 降低开发成本:考虑实际图片场景,提供不同场景下图片优化的最佳实践,降低图片优化成本。
总体可归结为
- 图片多采用 PNG 格式,压缩率低
- 预览图直接采用原始大小的图片,存在流量浪费且加载缓慢
- 图片渲染抖动,加载不流畅,在完成渲染前未采用占位图过渡
- 图片未进行懒加载
img引入方式
- 静态引入:代码中静态引入的图片,通常是跟随代码打包的图片,
此外也包括固定不变的远程URL;
代码中静态引入的图片,通常是跟随代码打包的图片,此外也包括固定不变的远程URL - 动态下发:服务端动态下发的图片,,这类 URL 相对较多且场景复杂
改造方案
引入图片优化组件,接入图片格式自适应、分辨率自适应、大小自适应
图片压缩等能力以减小图片大小,通过懒加载、过渡占位保证图片加载流畅性;
图片体积优化
主要通过图片压缩、格式自适应、分辨率自适应三种方式来减小图片体积
实现格式自适应
<picture>
<source srcset="image1.webp" type="image/webp" />
<img srcset="image1.jpg" decoding="async" loading="lazy"/>
</picture>
实现格式和分辨率自适应
<picture>
<source
srcset="image1.webp 200w,
image2.webp 600w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 50vw, 33vw"
type="image/webp"
/>
<img
srcset="image1.jpg 200w,
image2.jpg 600w"
sizes="(max-width: 480px) 100vw, (max-width: 768px) 50vw, 33vw"
decoding="async"
loading="lazy"
/>
</picture>
不过要注意的是,如果srcset和sizes属性设置不当,
可能会导致浏览器加载不必要的图片或者渲染出不合适的图片尺寸,
从而影响页面的加载速度和显示效果。因此,在使用这些属性时,
我们需要根据具体的情况进行优化和调整,确保图片的加载和显示效果都能达到最佳状态。
图片加载优化
图片加载优化包括懒加载、稳定性布局、占位图过渡、错误兜底等一系列措施,
保证图片加载的流畅性,提升用户体验。
同样参考 next/image 的思路,组件提供了五种稳定性布局:
intrinsic、responsive、fixed、fill、raw,
通过生成稳定的 dom 结构来提升视觉稳定性,尽可能覆盖大多数的图片场景
减少CLS累计布局偏移量
- intrinsic: 若指定宽度小于容器宽度,则根据指定宽高渲染图片;反之则图片宽度为容器宽,图片高度按照比例缩小;
- responsive: 图片渲染宽度等于容器宽度,高度按比例缩放;
- fixed: 根据指定宽高渲染图片;
- fill: 图片缩放以填充容器,可传入 objectFit、objectPosition
属性表示不同的填充模式; - raw: 组件中将不会插入布局相关的DOM,只保留纯净的 标签,
图片宽高将由组件中传入的宽高和 CSS 样式共同决定。
img监控
1. 加载耗时
PerformanceResourceTiming
该类指标包括请求资源过程中各个阶段的耗时、资源大小,以及由此推导而来的缓存命中指标
2. 压缩评估和分辩率评估
图片详情
图片格式、大小、尺寸、状态码等,依赖 MutationObserver 以及 Response Header 的信息
3. 格式评估
- 收集图片尺寸、体积、状态码以及浏览器信息;
- 判断浏览器对图片格式的支持性(可根据 ua 粗略判断 WebP、Avif )
- 上面 Jpeg 的压缩比取了 8 : 1,这里对齐Lighthouse,
保守估计 WebP 取 10 : 1,Avif 取 12 : 1; - 估算采用高压缩比格式后的体积,如果小于原图体积 8KB(插件里阈值取0)
以上,则认为该图可以进行格式优化。
4. 懒加载评估
该项评估分析是否有不在浏览器视窗内就已经加载的图片,
关键是判断图片加载后拉取图片的元素是否已经在视口内出现过,否则就记作没有懒加载。
如何判断元素是否在视口内出现过?
- MutationObserver 监听 dom 元素的增减,在新增元素时通过 IntersectionObserver 监听元素,
删除元素时停止监听;元素距离视口的阈值设置为100 - 若元素出现在视口范围内则更改 imgList 中该元素的状态,同时停止监听;
非首屏资源,NOSSR 或拆分异步加载
数据变化慢的进行接口拆分和接口缓存
图片webp
picture标签拥有兜底图片的特性,优先webp兜底jpg
可以先加载webp图片,监听
img的onerror和onload事件
来查看是否支持webp
svg使DOM结构过大
svg压缩和svgspring
6、 问题分析
JavaScript 在前端是单线程运行的,并且浏览器的一些其它计算行为也会阻塞 JavaScript 代码执行,比如 Paint & Layout。
7、优化应用的FCP
提升server性能是最直接的方式
- 优化dom结构(SVG Sprite)
dom结构复杂会对页面的Hydrate性能产生较大影响,也对ssr性能影响 - 前端请求替换成 Server 实现,直接服务端推送
直接调用 Node 端具体的某个函数直接获取数据,不用从前端请求绕一大圈 - 流式渲染
React/Vue 都支持流式渲染 API,流式渲染模式下,框架每渲染完一部分 HTML 就会直接响应。
由于 SSR 场景下页面已经填充好数据,越早返回数据浏览器就可以越早进行初次绘制,降低 FP 时间。 - 减少不必要的应用逻辑
找到不需要在服务端执行的复杂的逻辑,处理到客户端再执行
7、优化应用的LCP
DNS prefetch
HTTP2 的 Server push
8、 优化应用的 CLS
CLS 相对而言是比较容易拿到优化效果的指标,
而且该指标在 Lab 评分规则中占比重非常大。
根据 CLS 算法,我们只需要保证元素被渲染到页面上之后位置
不再有大幅度的移动即可得到一个比较高的 CLS 分数。使用骨架屏,
SSR 等都是比较常见的 CLS 优化手段。
9、优化TTI
在页面完全加载之前,尽量少的产生 Long task,尽量快的拿到请求响应
什么指标值得我们关注
https://juejin.cn/post/6956583036133572639