使用chatGPT,设计一套可落地的前端性能优化方案(上)

1,678 阅读9分钟

1、背景

昨天试了试,使用chatGPT创建了一个react项目,基本上成功创建了项目:

使用chatGPT创建一个react前端项目 - 掘金 (juejin.cn)

今天呢,试试让chatGPT(以下简称 “它”)给我们一个可以落地的前端性能优化方案,在开始之前呢,我设计了一个脑图,方便我们有结构的向GPT提问。

1680431437794.png

在开始之前呢,先要拉平一下认知,前端性能优化是一个很大的问题,处理这样的问题,不单单是某一项技术哦,问题多且零散,所以我们需要把这些性能问题管理起来,这里引入KPI考核中的一句话:你如果无法度量它,就无法管理它

也就是说,针对各项指标我们需要落实到,具体是哪些性能参数计算出的这些性能指标。可以看看上面的脑图,稍微理解一下。

再交代一下后端的方案,是我之前调研的一个比较成熟的方案,不在这次讨论范围,具体方案如下,感兴趣的同学可以抄个作业:

  • 部署一个nginx服务,且在可访问的路径中放入一个1px的gif
  • 使用页面的Image对象加载图片时,将页面的性能参数作为这个图片的请求参数,传给后台
  • 成功访问到这个gif时,nginx的assets日志会自动保存,URL的全部信息
  • 使用node或者kafka来读取日志,做清洗并落库,方便后边使用

废话有点儿多哈,接下来直接开始。

2、前端性能数据获取

首先就是获取,用户端的性能数据,关于这个问题,浏览器已经给我提供的相应的API,我也有相关的知识积累,主要是使用performce对象,但我的认知是否正确呢?

在写这篇文章的时候,我的认知还停留在使用performce.timing来获取性能数据,于是我MDN搜了一下:

1680436761781.png

官方已经不建议使用了,那如何替代呢,我是不想去繁琐的翻阅文档的,这里我们问一下GPT。

提问:performce.timing被废弃了,使用什么替代

1680437273864(1).png

对于这个被替代的方案,我担心,新的API会不会相较于timing会少一些参数,于是我追问了一下。

提问:对比一下performance.timing与performance.getEntriesByType('navigation')[0].toJSON() 的返回结果

1680437365040.png

从描述上来看,后者是包含前者,我大概也肉眼对比了一下,基本上是被包含与包含的关系。

第三个问题:performance.getEntriesByType('navigation')[0].toJSON()的返回结果有哪些,请逐个解释一下

这里我用,浏览器验证了一下,GPT给的参数数量不够(如下图),不过不是很重要,可能有些参数并不常用,如果后面我们有用到其他参数我们再修改这块的方案。

1680438661491.png

performance.getEntriesByType('navigation')[0].toJSON()返回的结果是一个JSON对象,包含了当前页面的性能数据。其中包括了以下属性:

  • connectEnd:最后一个网络请求结束的时间戳
  • connectStart:第一个网络请求开始的时间戳
  • domComplete:DOM渲染完成的时间戳
  • domContentLoadedEventEnd:DOMContentLoaded事件结束的时间戳
  • domContentLoadedEventStart:DOMContentLoaded事件开始的时间戳
  • domInteractive:DOM解析完成的时间戳
  • domainLookupEnd:DNS查询结束的时间戳
  • domainLookupStart:DNS查询开始的时间戳
  • duration:页面加载总耗时
  • encodedBodySize:页面内容压缩后的大小
  • entryType:性能条目类型,此处为navigation
  • fetchStart:第一个网络请求发起的时间戳
  • initiatorType:发起性能条目生成的类型,此处为navigation
  • loadEventEnd:load事件结束的时间戳
  • loadEventStart:load事件开始的时间戳
  • name:性能条目名称,此处为document
  • nextHopProtocol:下一跳协议,如h2、h3等
  • redirectCount:重定向次数
  • redirectEnd:最后一个重定向结束的时间戳
  • redirectStart:第一个重定向开始的时间戳
  • requestStart:第一个网络请求发起的时间戳
  • responseEnd:最后一个网络响应结束的时间戳
  • responseStart:第一个网络响应开始的时间戳
  • secureConnectionStart:安全连接建立开始的时间戳(HTTPS)
  • serverTiming:服务器计时信息,如TTFB等
  • startTime:性能条目开始的时间戳

我们将以上信息复制到脑图中,为了节约空间这里我收起了。心细的同学,可以每条都摘出来的哦~

1680438874225.png

3、前端性能指标都有哪些

好说完了参数,接下就是指标了,因为单一的参数是无法反应具体情况的。

提问:前端性能指标都有哪些?这些指标分别代表什么意思?

1680432370134.png

我让它,帮我总结了一下:

根据最新的chrome Lighthouse规则,前端的性能指标主要有:

  • FCP(First Contenful Paint):首次内容绘制时间,即浏览器首次绘制任何文本、图像、非空白canvas或SVG的时间。
  • SI(Speed Index):速度指数,即页面渲染速度的指标
  • LCP(Largest Contentful Paint):最大内容绘制时间,即页面中最大的可见内容元素绘制完成的时间。
  • TBT(Total Blocking Time):总阻塞时间,即页面主线程被阻塞的总时间。
  • CLS(Cumulative Layout Shift):累计布局偏移,即页面上所有元素在视觉上发生的意外移动的总和。
  • TTI(Time to Interactive)TTI是指页面变得可交互所需的时间
  • TTD(Time to Display)TTD是指页面显示所需的时间

然后,根据这段总结,我们把它转成脑图,如下:

1680439161394.png

很简单的复制转贴,那依据我们开始的原则,我们需要获得各个指标的计算方式,和获取方法。

3.1 FCP(First Contenful Paint)详解

提问:如何计算前端性能指标中的FCP请使用performance.getEntriesByType('navigation')[0].toJSON()中的参数计算

1680439461201.png

FCP是First Contentful Paint的缩写,指的是页面中第一次渲染出内容的时间点。FCP是页面性能指标中的一个重要指标,它可以反映出页面的首屏渲染速度。FCP的计算方法是:当浏览器渲染出页面中的第一个DOM元素时,记录下此时的时间戳,即为FCP时间戳。

具体获得方式及返回结果示例:

//获取FCP时间,返回一个时间戳
performance.getEntriesByType('navigation')[0].responseStart

3.2 SI(Speed Index)详解

提问:如何计算前端性能指标中的SI请使用performance.getEntriesByType('navigation')[0].toJSON()中的参数计算

1680440064952.png

1680440100417.png

SI是Speed Index的缩写,它是一种衡量页面加载速度的指标。SI是指页面在加载过程中,
用户能够看到的可视化内容的平均加载时间。SI值越小,页面加载速度越快,用户体验越好

具体获得方式及返回结果示例:

//获取si返回时间戳
let navigation = performance.getEntriesByType('navigation')[0].toJSON();
let si = navigation['loadEventEnd'] - navigation['domContentLoadedEventEnd'];

3.3 LCP(Largest Contentful Paint)详解

提问:如何计算前端性能指标中的LCP请使用performance.getEntriesByType('navigation')[0].toJSON()中的参数计算

1680440394163.png

LCP是一个以用户为中心的性能指标,可以测试用户感知到的页面加载速度,因为当页面主要内容可能加载完成的时候,它记录下了这个时间点。一个快速的LCP,可以让用户感受到这个页面的可用性 LCP的计算方法是:在页面上找到最大的文本块、图像或视频,并记录其加载时间。这个时间就是LCP。 具体获得方式及返回结果示例:

//获取LCP返回时间戳
let perfEntries = performance.getEntriesByType("navigation");
let lcp = perfEntries[0].largestContentfulPaint;

3.4 TBT(Total Blocking Time)详解

提问:如何计算前端性能指标中的TBT请使用performance.getEntriesByType('navigation')[0].toJSON()中的参数计算

1680440806273.png

TBT是Total Blocking Time的缩写,即总阻塞时间。它是指在页面交互性变为可靠前,不可交互程度的严重性。TBT是TTI的一个出色的配套指标,因为TBT有助于量化在页面交互性变为可靠前,不可交互程度的严重性。

具体获得方式及返回结果示例

//获取TBT返回时间戳
let navigationEntries = performance.getEntriesByType('navigation');
let navigationEntry = navigationEntries[0];
let navigationEntryJson = navigationEntry.toJSON();
let tbt = navigationEntryJson['totalBlockingTime'];

3.5 CLS(Cumulative Layout Shift)详解

提问:如何计算前端性能指标中的CLS请使用performance.getEntriesByType('navigation')[0].toJSON()中的参数计算

1680441164493.png

CLS是前端性能指标之一,它是用来衡量视觉界面稳定性的一个指标。CLS的计算方法如下:元素位移分数 (Layout Shift Score) = 影响范围 (Impact Fraction) * 移动距离 (Distance Fraction)。

其中,影响范围是指元素的面积占整个视口的比例,移动距离是指元素在视口中移动的距离与元素自身尺寸的乘积。

需要注意的是,如果使用getEntriesByType 来获取CLS的值,我们需要在页面加载完成后才能获取到,这意味着,我们获取性能的时机,应当在onload事件内,向后端传输性能数据。

具体获得方式及返回结果示例

const navigationEntries = performance.getEntriesByType('navigation');
if (navigationEntries.length > 0) {
  const navigationEntry = navigationEntries[0];
  const cls = navigationEntry.toJSON().cumulativeLayoutShift;
  console.log('CLS:', cls);
}

3.5 TTI(Time to Interactive)详解

提问:如何计算前端性能指标中的TTI请使用performance.getEntriesByType('navigation')[0].toJSON()中的参数计算

1680441740322.png

TTI是指页面从开始加载到主要子资源完成渲染,并能够快速、可靠地响应用户输入的时间。计算方法是在浏览器中模拟用户交互,然后记录时间戳,最后计算出TTI的时间。

具体获得方式及返回结果示例

const navigationEntries = performance.getEntriesByType('navigation');
if (navigationEntries.length > 0) {
  const navigationEntry = navigationEntries[0];
  const interactiveTime = navigationEntry.domInteractive - navigationEntry.navigationStart;
  const loadTime = navigationEntry.loadEventEnd - navigationEntry.navigationStart;
  const tti = interactiveTime + loadTime;
  console.log('TTI:', tti);
}

3.5 TTD(Time to Display)详解

提问:如何计算前端性能指标中的TTD请使用performance.getEntriesByType('navigation')[0].toJSON()中的参数计算

1680441932226.png

1680441954436.png

TTD是前端性能指标之一,它代表的是从用户请求页面到页面可交互的时间。具体来说,它是指从用户在浏览器地址栏输入网址开始,到页面上所有的主要资源都下载完毕并且可以交互的时间。 TTD的计算方法是:用户在浏览器地址栏输入网址开始,到页面上所有的主要资源都下载完毕并且可以交互的时间。

具体获得方式及返回结果示例

const navigation = performance.getEntriesByType('navigation')[0].toJSON();
const ttd = navigation.domInteractive - navigation.requestStart;

4 小结

由于篇幅所限呢,针对这些指标的优化方案,会放在下一篇文章来写

如果关注度足够的话,我会额外把,使用nginx作为前端性能日志收集的详细设计方案写出来哒~

最后呢,上面的信息我总结到了脑图

使用chatGPT优化性能指标.png

本文正在参加 人工智能创作者扶持计划