前端性能优化与计算方式

1.Navigation Timing

1.1 什么是Navigation Timing

Navigation Timing是一个性能优化方面为我们提供精准数据的工具,之前测试页面加载的时间都是在相应的位置打Date.now(),通过计算时间差来实现。这种做法有很多弊端

  • 需要在许多地方添加额外的代码
  • 记录的时间并不准确
  • 测试完之后需要找到每一个地方删除,容易落下且麻烦

W3C引入了 Navigation Timing API 帮我们自动,精准的实现了性能测试的打点问题。不仅帮我们省去了繁琐的手动打点的操作,而且提供了以前我们无法获取到的数据,比如DNS和TCP连接所需的时间。

加载一个页面时,一步一步怎么去做的。

图解
在这里插入图片描述
可分为以下三个阶段:
在这里插入图片描述

1.2 Navigation Timing具体说明

1.2.1 缓存处理阶段

  • navigationStart
    前一个文档卸载的时间戳

注:无上一层页面时,从fetchStart开始

  • unloadEventStart
    与前一个网页unload时的时间戳(卸载上一个网页),无上一个网页的时候,默认是0
  • unloadEventEnd
    执行完毕的时间戳
  • redirectStart / redirectEnd
    redirectStart:代表重定向的开始。表征了第一个HTTP重定向开始时的时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回0.
    redirectEnd:代表重定向的结束

做差值,用来计算重定向完成的时间

  • fetchStart
    表征了浏览器准备好使用HTTP请求来获取(fetch)文档的时间戳。

可聊点:
1.结合navigationStart,如果没有上一个页面的时候,fetchStart是整个全新开始页面的start
2.浏览器网络层ready的时间(可通过某个点减去fetchStart,计算出该点所用的时间)

1.2.2 网络请求阶段

  • domainInLookupStart / domainInLookupEnd
    DNS
  • connectStart / connectEnd
    TCP

网络的建立连接过程:connectEnd减去domainInLookupStart ,就是网络建立连接的耗时

secureConnectionStart
返回浏览器与服务器开始安全链接的握手时的Unix毫秒时间戳。如果当前网页不要求安全连接,则返回0。

建立安全链接 =>发散: http1.0 与 http2.0

  • 请求requestStart /响应responseEnd

整个请求的发起开始到完成接受的耗时

1.2.3 dom渲染阶段

  • domLoading
    开始解析渲染dom的时间(即Document.readyState属性变为“loading”、相应的 readystatechange事件触发时)

  • domInterActive
    完成了dom树的解析(即Document.readyState属性变为“interactive”、相应的readystatechange事件触发时),domInterActive减去domLoading就是解析dom树的时间。

可聊点:
1.完成dom树的解析,是不是整个页面的资源都加载完毕?
不是。只是完成了dom树的解析,并没有开始加载网页资源。
2.dom树的层级多了,会影响dom树解析的速度。

  • domContentLoaddedEventStart / domContentLoaddedEventEnd
    dom树解析完成后,资源的加载。domContentLoaddedEventEnd减去domContentLoaddedEventStart ,资源加载的时间。
  • domComplete
    Dom树ready(即Document.readyState 变为 'complete’且相对应的readystatechange 被触发时的Unix毫秒时间戳)。

domComplete减去domLoading,dom初始化的时间。

  • loadEventStart / loadEventEnd
    执行脚本开始与结束。
    loadEventStart : load事件被发送时的Unix毫秒时间戳。如果这个事件还未被发送,它的值将会是0。
    loadEventEnd:当load事件结束,即加载事件完成时的Unix毫秒时间戳。如果这个事件还未被发送,或者尚未完成,它的值将会是0.

1.3 使用

页面的卡顿流畅都是感官上的,以上的数据会给我们理性的衡量标准。

1.3.1 如何查看

在页面load完之后我们可以从performance.timing对象中拿到我们需要的所有数据:

在这里插入图片描述

1.3.2 项目中的使用

例1:计算页面加载所需的总时长:

   // index.html
    <script>
        javascript:(() => {
    
    
            const performance = window.performance.timing;
            const pageLoadTime = performance.loadEventEnd - performance.navigationStart;

            // pageLoadTime 为所求时间,可进行 打印、上报、存储
            console.log('当前页面加载耗时:', pageLoadTime, 'ms');
        })()
    </script>

例2:计算请求返回时长:

   // index.html
    <script>
        javascript:(() => {
    
    
            var connectTime = perfData.responseEnd - perfData.requestStart;
            // connectTime 为请求返回时长
        })()
    </script>

2.Core Web Vitals - CWV 网页性能三大指标

什么是CWV ?
Core Web Vitals (核心页面指标)是一种速度指标,是 Google 用于衡量用户体验的页面体验信号的一部分。 这些指标衡量是:最大内容绘制 (LCP) 的视觉负载、累积布局移位 (CLS) 的视觉稳定性、以及首次输入延迟 (FID) 的交互性。

加载、交互、视觉稳定 —— 代表不同方向的衡量标准 + 可衡量且接近真实体验的数据化参数

2.1 Largest Contenful Paint(LCP)

LCP 衡量加载性能——内容出现的速度。
最大内容绘制 (LCP) 报告视口内可见的最大图像或文本块的渲染时间。低于 2.5 秒的时间被认为是好的,而高于 4.0 秒的任何时间都被认为是差的。

要求:页面加载2.5s内,必须要进行最大内容的渲染。
什么是最大内容?

  1. 图片:<image>、<img>、<svg> 等
  2. <video>
  3. 通过url加载内容的模块(包括带有使用 CSS url()属性加载的背景图像的元素)
  4. 主要文本模块以及其内联模块(包含文本节点的块级元素)

2.1.1 LCP低下的原因(提升LCP的感知程度)

1.资源慢
解决=>缓存:强缓存+协商缓存
2. 渲染被阻断
解决=> 对于复杂的结构 :简化结构与逻辑、内联合并(结构、解析、脚本变简单,减少频繁的dom操作。 如MVVM框架,做一些dom diff,合并对于dom的频繁操作,改成一次性操作,尽量不去打断渲染)
3. 资源交互
图片分类 - 同一个图片分成几种(最大化提效,小页面不需要高精度,如列表页,只需要略缩图,不需要高清图。降低图片的质量和大小,提升最大内容的可显示速度,提高用户主观感受)
4. 静态资源
走CDN

扩展:关于图片上传

  1. 方法维度
    表单
    ajax
  2. 存储源纬度:
    直接推给后台:图片变成base64,发给后台
    云资源管理:图片上传到第三方托管的仓库,或者云容器,云容器返回id,将id返给后台,后台通过id,将业务逻辑与远端的图做一个关联。

2.2 First Input Delay(FID)

FID 衡量响应能力——页面对用户操作的响应速度。
该指标记录从用户与页面交互(点击、点击、按键等)到浏览器开始处理该事件处理程序的时间。小于 100 毫秒的延迟被认为是好的,而超过 300 毫秒的任何延迟都被认为是差的。

注: 它只测量事件处理的延迟——而不是运行处理程序或更新 UI 所花费的时间。

如果说LCP是衡量用户的第一眼感受的话,FID是衡量交互体验
要求:页面首次输入延迟小于100ms

2.2.1 FID的改进方式

1 减少 JavaScript 执行时间
a.优化算法
b. 尽量减少JS的占用 (空间、时间)
空间:进行压缩,减少JS的体积
c. 首屏加载

如何优化SPA?

  • 服务端渲染
    解决SPA问题:不用SPA,后台渲染好,返回静态页
  • 使用预加载、懒加载

2. 分解长时间运行的任务(解决长任务问题)
长任务:一个任务可能会阻塞整个渲染。阻塞渲染50ms以上。
解决:

  • 尽量拆分
    如果是纯前端的问题,超过50ms,尽量做拆分。一段一段去执行,每执行一段,渲染出来,有一个阶段性的样子
  • 做交互弥补
    比如有的网络请求没办法拆分,一个网络请求要很久,可以加loading框、加载中…

*3 提升性能来帮助提速(使用Web Worker在后台线程中运行任务
JS workers:Web wor ·ker | service worker | worklet

 // 1. web worker
    /* main.js */
    // 新增一个worker
    const worker = new Worker('worker.js');

    // main thread 通信
    worker.postMessage('Come on & work~');
    worker.onmessage = function(e) {
    
    
        console.log(e.data);
    }

    /* worker.js */
    self.onmessage = function(e) {
    
    
        console.log(e.data);
        // 回调主人喊话 => 业务逻辑

        // 完成后发给main
        self.postMessage(/* 业务逻辑 */);
    }

    // 2. service worker - 网络 + 内存
    /* main.js */
    navigator.seviceWorker.register('service-worker.js');

    /* service-worker.js */
    self.addEventLister("install", function() {
    
    });
    self.addEventLister("activate", function() {
    
    });
    self.addEventLister("fetch", function(e) {
    
    
        e.respondwith(
            caches.match(event.request);
        )
    });

    // 3. worklet
    // 浏览器概念流程: JS => style => layout => paint => composite

    /* main.js */
    CSS.paintWorklet.addModule('worklet.js');

    /* worklet.js */ 
    registerPaint('myGradient', class {
    
    
        paint(ctx, size, prop) {
    
    
            var gradient = ctx.createLinearGradient(0, 0, 0, size.height - 5);

            gradient.addColorStop(0, "black");
            gradient.addColorStop(1, "white");

            ctx.fillStyle = gradient;
            ctx.fillRect(0, 0, size.width, size.height);
        }
    })

    /* app */
    .content {
    
    
        background-image: paint(myGradient);
    }

2.3 Cumulative Layout Shift(CLS)

CLS 测量视觉稳定性 -查看页面时内容的意外移动。

衡量视觉稳定向
要求:页面要保持CLS小于0.1(可见元素从前一帧到后一帧改变位置的动作 就代表视觉稳定性)
可见元素已经在处于可见态,前一帧到后一帧位置动作的改变就是降低视觉稳定性的一种体验。页面点击一下或者加载的时候,本来出现在左边突然间往右移,闪烁和漂移,这是主观上的感受,量化之后就是CLS。

换句话说:如果页面上的元素随着页面加载而移动,那么CLS就会变高,这是不好的。相反,你应该希望页面元素在加载时相当稳定。这样,当页面完全加载时,用户不必重新学习链接,图像和字段的位置,或者错误地点击某些内容。

2.3.1 减少 CLS(如何保持视觉稳定性?)

1 不使用无尺寸元素
对任何媒体(视频、图片、GIF、信息图表等)使用设置大小属性维度:这样,用户的浏览器就可以确切地知道该元素将在该页面上占用多少空间。
扩展: 自适应并不是无尺寸,是一定衡量标准下的有尺寸
srcset & sizes

 <img srcset="zhaowa-320w.jpg 320w,
                zhaowa-480w.jpg 480w,
                zhaowa-800w.jpg 800w,"
        sizes="(max-width: 320px) 300px,
                (max-width: 480px) 440px,
                800px">

2 减少内容内部的插入
(减少 重绘、重排)
会影响到整体的布局
3 字体控制
字体变化大小会导致 外层容器的变化,font-style、font-family变化也会导致视觉上元素不稳定。

对于字体,目标是尽可能快地在屏幕上显示字体,而不是与其他字体交换。在加载网络字体时避免 FOUT(无样式文本的闪烁)和 FOIT(不可见文本的闪烁)。预加载或使用类似大小的后备字体将有所帮助

2.4 Core Web VItals Annotetions - 衡量CWV的工具

下载 Core Web VItals Annotetions 点击这里
2.4.1 使用
例:使用Core Web VItals Annotetions测试百度翻译
在这里插入图片描述
右侧展示为FID、LCP、CLS测量信息,页面中标注为CLS偏移部分。

2.4.2 高效的优化方法
评估 LCP、FID 和 CLS 指标可以帮助确定最关键的问题。解决快速而简单的问题——它们通常具有最大的投资回报:

  • 激活服务器压缩和 HTTP/2 或 HTTP/3
  • 通过设置 HTTP 过期标头确保使用浏览器缓存
  • 尽早预加载资产
  • 连接和缩小 CSS 和 JavaScript
  • 删除未使用的资产
  • 考虑使用 CDN 或更好的托管
  • 使用适当的图像大小和格式
  • 优化图像和视频文件大小(专业 CDN 可以提供帮助)

3. performance - 性能评估神器

3.1 什么是performance ?

performance定位神器:接到一个任务,这个页面比较慢、性能差。属于感官上的感受 ,不好量化。performance可以把它量化出来,并找到慢的原因。

可把performance理解为对性能评估领域的一个接口,可以通过performance拿到很多性能上的参数,通过performance去定位哪里有问题,哪里有问题改哪里。

一个页面性能评估的领域:
1.存储有没有问题:FPS(帧率),CPU(占用、资源的消耗)、网络请求(的多少)
2.网络请求有没有问题:网络任务队列(如何排列的,并行还是串行)
3.代码执行有没有问题:JS消耗时间、性能占用(确认代码的书写有没有需要改进的地方)
4.布局(layout) 有没有问题:浏览器绘制页面的帧布局

点击刷新开始
在这里插入图片描述

3.2 performance的使用

由于本文篇幅较长,故提取成单独文章:
点击查看-使用详解

*3.1 大厂监控体系

比较完善,自动化的形式,规则的去看系统的性能

  1. 上报 => 采集 => 数据回收 => 获取场景数据
  2. 数据分析 => 根据上报的信息做timing节点计算 => 阈值设置 + 数据分类 + 数据重组
  3. 可视化展示

growing.io => fineBi / powerBi => grafana => 钉钉、企业微信、飞书 webhook

*3.2 性能优化的另一种可能 - bigpipe —— 页面分解成若干的pagelet

BigPipe 是由 Facebook提出来的一种动态网页加载技术。它将网页分解成称为 pagelets 的小块,然后分块传输到浏览器端,进行渲染。它可以有效地提升首屏渲染时间。

为了使得浏览器和服务器可以并行的执行某些操作,BigPipe 首先需要我们将网页分割成被称为 pagelet 的小块。然后我们将网页交付流程分解为如下阶段:

  1. 解析请求:服务器校验和解析 HTTP 请求
  2. 数据拉取:服务器从接口或数据库获得数据
  3. HTML 标记生成:生成对应的 HTML 片段
  4. 网络传输:服务器返回响应到浏览器
  5. CSS 下载:浏览器下载需要的 CSS 文件
  6. 构建 DOM 树和应用样式:浏览器构建 DOM 树,并将相应的 CSS 样式规则应用到节点上
  7. JavaScript 下载:下载网页引用的 JavaScript 文件
  8. JavaScript 执行:浏览器执行下载后的 JavaScript
  1. 服务前端接收客户端请求
  2. node生成HTML * n => 若干个pageLet
  3. 浏览器获取到pagelet后开始加载资源做layout paint
  4. 客户端整合形成页面

猜你喜欢

转载自blog.csdn.net/weixin_44247866/article/details/128457028