性能优化,看这篇就够了~

846 阅读22分钟

当我们正在coding的时候,突然出现了一个"钉~", 你打开一看,是产品扔了个链接过来。

产品:你这个页面有点卡哦~ 能不能优化下~?

然后你按着他的步骤操作了一下,嗯,是有点卡哦~

这个时候我们怎么来检测到底是哪部分出现的问题导致页面卡顿了呢?

所以为了更好的做性能优化,我就整理了一些性能工具以及使用方法来帮助我做页面的性能检测,现在也把它分享给有同样困惑的童鞋。

但是在介绍工具之前,我们得了解性能指标,以帮助我们后面理解工具检测出的性能报告。所以今天的主题就是性能优化之性能指标。目前主要有了解以下2个就可以了。

一.RAIL 性能模型

RAIL是Response,Animation,Idle和Load的首字母缩写,是一种由Google Chrome团队于2015年提出的性能模型,用于提升浏览器的用户体验和性能。
RAIL模型的理念是以用户为中心,最终目标并不是让你的网站在任何特定设备上都能运行很快,而是使用户满意。

Response: 应该尽可能快速的响应用户的操作,应在在100ms以内响应用户输入。

Animation: 在展示动画的时候,每一帧应该以16ms进行渲染,这样可以保持动画效果的一致性,并且避免卡顿。

Idle: 当使用js主线程的时候,应该把任务划分到执行时间小于50ms的片段中去,这样可以释放线程以进行用户交互。50ms为单位是为了保证用户在发生操作的100ms内做出响应。

要使网站响应迅速,动画流畅,通常都需要较长的处理时间,但以用户为中心来看待性能问题,就会发现并非所有工作都需要在响应和加载阶段完成,完全可以利用浏览器的空闲时间处理可延迟的任务,只要让用户感受不到延迟即可。利用空闲时间处理延迟可减少预加载的数据大小,以保证网站或应用快速完成加载。

Load: 应该在小于1s的时间内加载完成你的网站,并可以进行用户交互。根据网络条件和硬件的不同,用户对性能延迟的理解也有所不同,在3G网络需要花费更多的时间,5s是一个更现实的目标。

基于用户体验的性能指标其中包括以下几个比较重要的性能指标。

(1)FCP (First Contentful Paint)

首次内容绘制,浏览器首次绘制来自DOM的内容的时间,内容必须包括文本,图片,非白色的canvas或svg,也包括带有正在加载中的web字体文本。这是用户第一次看到的内容。

 FCP时间(秒)  

颜色编码 

FPC分数

0 - 2 

绿色(快) 

75 - 100

 2 - 4 

橙色(中等) 

50 - 74

超过4 

红色(慢) 

0 - 49

(2) LCP (Largest Contentful Paint)

最大内容绘制,可视区域中最大的内容元素呈现到屏幕上的时间,用以估算页面的主要内容对用户的可见时间。img图片,video元素的封面,通过url加载到的北京,文本节点等,为了提供更好的用户体验,网站应该在2.5s以内或者更短的时间最大内容绘制。

LCP时间(秒)

颜色编码

0 - 2.5

绿色(快)

2.5 - 4

橙色(中等)

超过4

红色(慢)

(3) FID (First Input Delay)

首次输入延迟,从用户第一次与页面进行交互到浏览器实际能够响应该交互的时间,输入延迟是因为浏览器的主线程正忙于做其他事情,所以不能响应用户,发生这种情况的一个常见原因是浏览器正忙于解析和执行应用程序加载的大量计算的JavaScript。

FID时间(毫秒)

颜色编码

0 - 100

绿色(快)

100 - 300

橙色(中等)

超过300

红色(慢)

(4) TTI (Time to Interactive)

网页第一次完全达到可交互状态的时间点,浏览器已经可以持续的响应用户的输入,完全达到可交互的状态的时间是在最后一个长任务完成的时间,并且在随后的5s内网络和主线程是空闲的。从定义上来看,中文名称叫持续可交互时间或可流畅交互时间更合适

TTI时间(秒)

颜色编码

0 - 3.8

绿色(快)

3.9 - 7.3

橙色(中等)

超过7.3

红色(慢)

(5)TBT (Total Block Time)

总阻塞时间,度量了FCP和TTI之间的总时间,在该时间范围内,主线程被阻塞足够长的时间以防止输入响应。只要存在长任务,该主线程就会被视为阻塞,该任务在主线程上运行超过50毫秒。

线程阻塞是因为浏览器无法中断正在进行的任务,因此如果用户确实在较长的任务中间与页面进行交互,则浏览器必须等待任务完成才能响应。

TBT时间(毫秒)

颜色编码

0 - 300

绿色(快)

300 - 600

橙色(中等)

超过600

红色(慢)

(6)CLS (Cumulative Layout Shift)

累计布局位移,CLS会测量在页面整个生命周期中发生的每个意外的布局移位的所有单独布局移位分数的总和,他是一种保证页面的视觉稳定性从而提升用户体验的指标方案。

用人话来说就是当点击页面中的某个元素的时候,突然布局变了,手指点到了其它位置。比如想点击页面的链接,突然出现了一个banner。这种情况可能是因为尺寸未知的图像或者视频。

CLS时间(毫秒)

颜色编码

0 - 0.1

绿色(快)

0.1 - 0.25

橙色(中等)

超过0.25

红色(慢)

二.Web Vitals

在2020年Google 推出新的使用者体验量化方式: Web Vitals。web-vitals 集成了 5 个指标的 api,核心指标有 3 个: 加载性能LCP,交互性FID,视觉稳定性CLS。只需要做好这三个,网站的性能基本上就可以了。
测量Web Vitals的工具有很多,比如Lighthouse,web-vitals,浏览器插件web vitals。

image.png

1. web-vitals

可在代码中直接获取Web-Vitals的3个核心指标,然后进行上报。

// npm install web-vitals -g
import { getLCP, getFID, getCLS } from ‘web-vitals’;
getCLS(conole.log)
getFID(conole.log)
getCLS(conole.log)

2. web vitals浏览器插件

谷歌浏览器有插件web vitals。安装完成之后浏览器的右上角会有插件标志,点击就会显示页面的性能指标。这个我们将在下面详细讲到。

三.性能工具

1. Chrome DevTools

(1). Performance

说起性能工具,相信大家想到的第一个肯定是chrome 的performance。Performance面板主要对网站应用的运行时性能表现进行检测和分析,包括页面的每秒帧数,CPU的消耗和各种请求花费的时间等,主要分为一下3部分,下面我们来一个一个的认识。

image.png

第一部:概览

主要是整体界面渲染的时候,每个时间段执行的事件顺序,通过上图我们就能知道我们每个时间段(精确到毫秒)都做了什么,当鼠标放上去的时候,我们还可以通过大图去查看我们每个时间段界面的渲染情况,Performance 会将几个关键指标,诸如页面帧速 (FPS)、CPU 资源消耗、网络请求流量、V8 内存使用量 (堆内存) 等,按照时间顺序做成图表的形式展现出来。

上下箭头
用来上传和下载每一次性能检测报告。

no recordings
下拉可以切换不同的检测报告,从而去进行性能优化的对比。

image.png

Screenshots(勾选显示下图)
用来查看在每个时间段界面的变化,鼠标放上去可以查看每个时间的界面渲染情况的大图。

image.png

Memory(勾选显示下图)
通过该图我们可以追踪内存泄漏问题。比如 JS Heap(堆),如果曲线一直在增长,则说明存在内存泄露,如果相当长的一段时间,内存曲线都是没有下降的,这里是有发生内存泄露的可能的。鼠标移上折线图后可以看到每项内存占用情况。
jsHeap: js 内存消耗大小
Documents: dom 文档数
Nodes: 内存中dom 的 节点数
Listeners: 内存中元素绑定的事件数

image.png

配置(点击显示下图)

image.png
Disable Javascript samples 禁用
Enable advanced paint instrumentation (slow) 记录渲染事件的细节
Network 模拟不同速度的网络情况
cpu 模拟cpu不同处理速度

FPS
每秒传输帧数,当动画以60FPS运行时,我们肉眼看上去动画是流畅的。
image.png

当我们看到FPS上方显示红色条的时候,意味着我们的帧率特别低,可能出现卡顿掉帧,导致用户体验不好。一般来说,绿色条越高,FPS越高。 所以我们分析性能图表第一眼看的就是FPS。

CPU
image.png

颜色对应性能面板底部环形图图表的颜色。我们可以看到哪部分的耗时是最长的,然后针对这部分进行优化。我们可以看到上图耗时最长的是Scripting 部分,所以我们可以看看我们的代码是否有优化的地方。

NET
横杠越长,检索资源所需的时间越长。 每个横杠的浅色部分表示等待时间(从请求资源到第一个字节下载完成的时间)。我们可以通过放大长条比较长的部分查看耗时的具体事件。
image.png

HEAP
每个时间堆内存使用情况。对应内存图表中JS Heap。
image.png

第二部分:火焰图

Networt
可以直观的看到资源加载的顺序与时长。我们可以看到,资源是并行加载的。请求也通过颜色进行了标识,黄色表示是script文件,蓝色表示是html文件,紫色表示是css文件,绿色表示是媒体文件,灰色表示各种其他文件。请求左上角的深蓝色方块表示它是更高优先级的请求。浅蓝色方块表示较低优先级。 点击某个请求在下面summery 可以看到更多的详细信息。

image.png
image.png
image.png

我们放大某一个请求,其实就会发现它和netWork的Timing 是相互对应的。比如左边的那条线其实就是ConnectionStart中包含的事件(DNS 解析,建立HTTP连接等)的耗时,也就是发送请求之前的一些事件的耗时,长条浅色部分就是Request sent 和Waiting 的时间,深色部分是Content Download的耗时, 右边的线基本就是等待主线程的耗时,在Timing 中没有体现。通过分析,如果我们发现某一个请求的深色部分比较长,就说明这个文件比较大,可能需要优化。如果发现浅色比较长,可能是等待服务器返回数据的时间比较长。从而找出是前端还是后端需要优化。

Frames
查看我们在什么时间,界面发生了改变,它和第一部分的区别就是在界面没有改变的时候,它是不做记录的,但是概览部分是会做记录的。将鼠标悬浮在绿色方块上,DevTools会显示特定的帧消耗时间。每帧可能远低于60FPS的目标。上图中一帧耗费157.2ms,那么它的FPS为6(1000ms/157)。 远远低于60FPS的要求。

image.png

另一个非常方便的工具是FPS计数,可以在页面运行时提供对FPS的实时估计。

Command + Shift + P(mac) 输入 fps 选择显示渲染。就会在浏览器中出现监控面板。

image.png

image.png

Interactions
记录用户交互操作,比如点击鼠标、输入文字、动画等。如果没有交互动作的时候,是不会有这部分的功能。

image.png

Timings
记录一些关键的时间节点在何时产生的数据信息,诸如DCL、 FP、FCP、LCP、L 等。在项目打包后,就没有对应的事件调用,所以在线上经过打包的网站,是看不到这部分的。

image.png

Main
performance核心部分,记录了渲染进程中主线程的执行记录,点击main可以看到某个任务执行的具体情况,是我们分析具体函数耗时最常看的面板。

image.png

当某任务耗时比较长的时候右上角会出现一个红色三角被标识为长任务。比如,我们可以看到Animation Frame Fired(只要执行requestAnimationFrame就会有此回调) 右上角有红色三角形。单击Animation Frame Fired,底部Summary 栏会显示有关该事件信息,并附带源码链接。单击链接会跳转到源码相关行,就可以看到耗时的代码。

Compositor
合成线程的执行记录,用来记录html绘制阶段 (Paint)结束后的图层合成操作。

image.png

Raster
光栅化线程池,用来让 GPU 执行光栅化的任务。记录在前端部分一共使用了几条线程(浏览器渲染的线程)。

image.png

GPU
GPU进程主线程的执行过程记录,如可以直观看到何时启动GPU加速…

image.png

第三部份:性能检测详情

Summary(性能摘要)
统计在我们检测性能的时间范围内,都做了哪些事情。

image.png

Loading :加载时间
Scripting :js执行时间
Rendering :渲染时间
Painting :绘制时间
Other :其他时间
Idle :浏览器闲置时间。
我们主要关注js 执行时间和渲染时间。

Bottom-Up(事件时长排序列表,倒序,对应 Main 火焰图)
从这里,我们可以看见所有的事件列表,还有每个事件的 Self Time(自己调用的时间) 、 Total Time(总调用时间,包括子项调用时间) 、 Activity(行为,包括调用该事件的位置)。在 Activity 的右侧,部分还带有 Source Map 链接,点击之后可以定位到相应操作对应的代码。使用它可以比较方便地定位到具体的代码。可以通过不同类型进行分类查看。

image.png

Call Tree(事件调用顺序列表)
其实这里和 Bottom-Up 部分是一样的,就不做太多的说明了,大家看一下就知道了。

image.png

Event log(按事件发生顺序记录的事件日志)
比前面的 Bottom-Up 和 Call Tree 相比,多了一个 Start Time 属性,这个属性其实就是开始的时间,从什么时间开始执行的什么事件。可以根据耗时和类型进行筛选。

image.png

PerformanceAPI

performance 面板的可视化图形界面让我们可以直观的看到文件的加载顺序,每毫秒界面展示的效果,每个方法执行的顺序和时间(由下至上)等等,但是他是无法查看某一个区间之内的运行时间,无法查看页面是刷新还是加载,重定向次数等,所以我们可以通过performanceAPI 来弥补这个缺点。

下面就介绍几个比较实用的performanceAPI。

Performance.navigation(操作相关)

该属性是一个对象,有两个属性值,分别是 redirectCount(重定向次数) 、 type(操作的类型):

redirectCount

该属性值为几,就说明了当前页面重定向了多少次;

type

type(0):当前页面是通过点击链接,书签和表单提交,或者脚本操作,或者在url中直接输入地址;

type(1):点击刷新页面按钮或者通过Location.reload()方法显示的页面;

type(2):页面通过历史记录和前进后退访问时;

type(255):任何其他方式

Performance.now(): 返回一个表示从性能测量时刻开始经过的毫秒数

当然,我们也可以在代码中使用 [使用 Performance API 获取页面性能](Performance API) 获取页面性能。

(2)其他

当然,Chrome DevTools中除了performance面板以外,也有其他的面板可以帮助我们查看网站性能问题。

浏览器的任务管理器

可以查看当前Chrome浏览器中,所有进程关于GPU,网络和内存空间的使用情况,这些进程包括当前打开的各个标签页,安装的各种扩展插件,以及GPU,网络,渲染等浏览器的默认进程,通过监控这些数据,可以定位可能存在内存泄露或网络资源加载异常的问题进程。
启动台-> 其他 -> 活动监视器(mac)

image.png

可以看到所有进行的进程以及内存占用网络消耗。

Network网络分析

Network面板是一个常被用到的工具,通过它可以获取到网站所有资源的请求情况,包括加载时间,尺寸大小,优先级设置以及HTTP缓存等信息。可以帮助开发者发现可能由于未进行有效压缩而导致资源尺寸过大的问题,未配置缓存策略导致二次请求加载时间过长的问题。

image.png

缓存测试

Disable cache

image.png

吞吐测试,模拟网速

image.png

Coverage

监控并统计出网站应用运行过程中代码执行的覆盖率情况。

统计的对象是JavaScript脚本文件与css样式文件,统计结果主要包括文件的字节大小,执行过程中已覆盖的代码字节数,可视化的覆盖率条形图。

根据执行结果可以发现到底哪些尺寸较大的代码文件覆盖率较低,这就意味着这些代码文件中可能存在较多的无用代码。

command + shift + p 搜索 coverage 就会显示出来。可以看到第一个文件有20.6%没有被使用到,第二个有93.1%没有使用到。

image.png

Memory 面板

主要用于分析内存占用情况,如果出现内存泄露,那么就可能带来网站崩溃的后果。

为了更细致和准确的监控应用网站当前的内存使用情况,Chrome浏览器提供Memory面板,可以快速生成当前的堆内存快照。

image.png

结束后可以查看到内存占用大小,就可以对对应的模块进行优化。

image.png

monitor

可以使用性能监视器,这是一个实时的监视器。

command + Shift + P 输入 monitor。

image.png

2. React Profiler

相信做react开发的同学浏览器都会安装 React Developer Tools,当我们安装好后会发现Chrome DevTools里面有个Profiler 面板,使用这个面板也能帮助我们做性能优化。

image.png

点击记录按钮开始记录,我们像往常一样对网站进行操作,工具会自动收集性能数据,然后再次点击记录按钮结束记录。
profiler 是在提交阶段收集性能数据的。 下图中每一列都表示单次提交的记录。 你可以点击各个列(或者是左/右切换按钮)来查看不同的提交的数据。
这些列的颜色和高度对应该次提交渲染所需的时间。 (较高的黄色的列比较短的蓝色的列耗费的时间长。)我们可以关注黄色并且高的列。

image.png

点击设置按钮可以通过时间筛选提交记录。也可以选中显示每次组件渲染的原因。

image.png

记录的性能数据包括4个部分:1.火焰图 2.排序图 3.时间线 4.组件图

Flamegraph(火焰图)

显示单次提交下网站的状态。每个长条就是一个组件,他的长度显示了组件渲染的耗时,点击某个组件,右边会显示这次提交组件渲染的原因以及渲染了几次(包括渲染的开始时间与耗时)。
组件的颜色不同标识这个组件渲染耗时的不同:
黄色:组件渲染耗时较长。
蓝色:组件渲染耗时较短。
灰色:在这次commit 里组件没有重新渲染。
每个组件后面的括号里是自己渲染的耗时与和子组件一起一共渲染的耗时。如果它自己的耗时比较短,但是后面显示的耗时比较长,那么我们就要查看是否是他的某个子组件耗时比较长,然后针对这个组件进行优化。

image.png

Ranked(排序图)

当然我们可以直接查看排序图,它会将这次提交里渲染的组件按照渲染耗时进行一个排序,耗时最长的在最上面。这样我们就能一眼看出那个组件耗时最长,然后就可以针对这个组件进行优化。

image.png

3.Lighthouse

Lighthouse 是一个网站性能测评工具, 它是 Google Chrome 推出的一个开源自动化工具,能够对 PWA 和网页多方面的效果指标进行评测,并给出最佳实践的建议以帮助开发者改进网站的质量。
它能够生成一个有关页面性能的报告,通过报告我们就可以知道需要采取哪些措施来改进应用的性能和体验。
运行lighthouse需要Node >= 8.9 , Chrome 浏览器 >= 79,否则 lighthouse 可能会运行失败,或者是某些指标无法显示出来.

lighthouse 使用方法

(1)chrome 插件(需要FQ)

安装lighthouse 后,浏览器右上角有个灯塔图标,devTools 里面也有个lighthouse 选项。点击Generate report 生成如下图的报告。

image.png

当你根据报告的提示一一优化后,可以点击上图+ 号可以再次生成报告。然后可以切换多次的报告进行查看比较。

image.png

(2)使用npm 包 lighthouse

npm install -g lighthouse
lighthouse http://www.baidu.com/

默认情况下,会在执行命令的当前目录下生成一个 HTML 文件,直接打开该文件即可查看报告。
lighthouse

lighthouse http://www.baidu.com --view   //直接通过浏览器打开HTML报告
lighthouse http://www.baidu.com --output json  //结果以 json 格式文件输出
lighthouse http://www.baidu.com --output json --output-path ./myfile.json   //指定结果文件输出的目录
lighthouse https://baidu.com --output html --output-path ./report.html   //指定结果文件输出的目录

其他参数可参考 lighthouse的 github 官网:github.com/GoogleChrom…
json 格式的报告可以通过 googlechrome.github.io/lighthouse/… 这个地址来打开。
当然还可以通过直接克隆github上的lighthouse开源项目使用,在node中以编程方式引入lighthouse模块等。

lighthouse 报告分析

lighthouse 报告包括了性能(Performance),访问无障碍(Accessibility)最佳实践(Best Practice)搜索引擎优化(SEO),**PWA(Progressive Web App)**五个部分。

(1)性能(Performance)

包括MetricsDiagnosticOpportunities 三部分。
metrics 的指标会对分数产生直接影响。各个指标对性能评分的贡献并不相同,权重较大的指标,对性能评分的影响更大一些(各指标权重分配情况)。
Opportunities 它提供了详细的建议和文档,帮助我们优化与改进。每条都可以展开查看详细建议。
Diagnostics 显示应用优化的相关信息。每条都可以展开查看详细问题。

image.png

(2)访问无障碍(Accessibility)

无障碍性的每个指标项测试结果为pass或者fail,当页面只是部分通过某项指标时,页面的这项指标将不会得分。

image.png

(3)最佳实践(Best Practice)

可以展开查看哪些是最佳实践,哪些不是有待改进。

image.png

(4)搜索引擎优化(SEO)

比如:图片元素使用 alt 属性等等提高搜索引擎搜索排名,便于搜索引擎能找到你这个网站。

image.png

(5)PWA(Progressive Web App)

如果你的网站是PWA 则这项会高亮,不是则是灰色。

image.png

页面的最后是检测页面的一些信息。

image.png

4. Web Vitals

安装chrome 插件 Web Vitals(需要FQ),当你访问的时候,该插件就会检测你网站的性能指标。如下图,由此可以看出我们的网站还有优化的空间。

image.png

image.png

5. pageSeed Insights

PageSpeed Insights 是由谷歌官方开发的一款可以分析页面载入的各个方面,包括资源、网络、DOM以及时间线等等信息的检测工具。

(1)chrome 插件 pageSpeed Insights。(需要FQ)

image.png

点击start analyzing,生成检测报表,每项展开都可以看到详细结果。我们可以根据这些建议对网站进行一一的优化。

image.png

点击配置会新开一个chrome tab,可以根据自己的需求设置pageSpeed Insights 的相关配置。这个插件有个好处就是可以设置语言,对于英语不咋好的童鞋是不是很友好呢~

image.png

(2)在线版(只能检测外网能访问的地址)

在线检测地址:developers.google.cn/speed/pages…

image.png

中文网地址: www.googlespeed.cn (只能测速,没有优化建议和诊断结果)

image.png

6. WebPageTest

在线测试网站: www.webpagetest.org/(需FQ)
这个网站比较适合测试国际网站。而且只能测试已经发布的网站。
通过高级配置,可以模拟网站的访问地址(地理位置),浏览器,网络情况等等。

image.png

测试结果会显示网站检测的指标, 真实用户体验数据,可以查看网站加载的视频。

image.png

image.png

可以比较每次测试的结果。查看每次检测的详细报表。

image.png

当然,如果你感兴趣的话,这个网站有更多功能值得你继续去探索。

好了,介绍了这么多网站性能测试工具,我们在做性能优化的时候并不是所有的工具都要用上。当我们对某个页面做性能优化测试的时候,可以用Performace 或是React Profiler,当我们想对整个网站做一个性能测试并进行优化的话,大家可以用lighthouse, pageSeeds,WebPageTest,大家可以根据自己的网站类型,网络情况以及使用习惯,选择适合自己的就可以了。希望大家能学以致用,使网站有个更好的用户体验~

最后推荐下我的个人网站- 【良月清秋的前端日志】(animasling.github.io/front-end-b…) ,希望我的文章对你有帮助。