性能,性能,性能. 你可以拥有世界上最好的网站,但如果需要2分钟才能加载,没有人会看到它. 如果你的网站需要2分钟才能加载,很可能不难弄清楚为什么。
有许多工具可以帮助您了解您的应用程序如何在本地工作。性能API在这里帮助我们对我们的网页有细微的了解。您可以获取真实的数据,并看到您的网站如何在不同的浏览器,网络,世界各地和更多地方工作!
性能 API 通常被描述为 APIs 的组合,有太多的东西可以用一个文章来描述所有内容,在本文中,我们将向您展示最基本的功能,以便您开始跟踪性能。
API正在演变,有许多新功能和折扣即将到来。所有性能 API 的 2 级正在出现;其中一些已部分实施,其中一些仍然是草案。
如何访问性能数据
业绩:现在
最基本的方法来衡量一个程序的性能是使用 performance.now()
. 这将以微分秒分辨率返回当前时间. 如果你想挖掘高分辨率的时间,我强烈建议你阅读W3C的编辑关于该主题的草案(https://w3c.github.io/perf-timing-primer/#high-resolution-time)。
「performance.now」只允许您测量您的JavaScript代码中的内容(也称为用户性能)。
要访问不同的 DOM 和浏览器事件,我们有 3 个功能:
getEntries()
返回所有可用的性能条目. 尝试在当前页面上运行performance.getEntries()
,你会看到一个大数组。 最初,大多数条目将与页面(也称为资源)加载的所有图像、脚本和其他东西有关
1const tenthEntry = performance.getEntries()[10]
2// on Alligator.io it will return the following object
3// { initiatorType: "script",
4// nextHopProtocol: "h2",
5// workerStart: 526.8099999520928,
6// redirectStart: 0,
7// ....
8// decodedBodySize: 0,
9// serverTiming: [],
10// name: "https://d33wubrfki0l68.cloudfront.net/bundles/e2203d1b1c14952473222bcff4c58a8bd9fef14a.js",
11// entryType: "resource",
12// startTime: 315.5049999477342,
13// duration: 231.48499999661
14//}
15// We can see this is a resource entry for a script loaded from cloudfront
- getEntriesByType()类似于
getEntries()
,但会给你一些过滤结果的可能性
您可以查询的6种类型:
- 框架:一个非常实验性的功能,允许开发人员在一个事件循环中获取浏览器所做的工作量的数据。如果浏览器在一个循环中做过多的工作,则框架率会下降,用户体验将很差. *资源:这涉及到网站下载的所有资源 *标记:这些是可用于计算代码的速度的自定义标记 *测量:措施使我们能够轻松地测量两个标记之间的差异 *油漆:油漆条目与屏幕上显示的像素有关 长任务:长任务是执行超过50ms的任何任务
我们将在下一节中深入了解一些这些类型,这里有一个简单的例子来开始:
1const paintEntries = performance.getEntriesByType('paint')
2// paint Entries[0] equals {
3// name: "first-paint",
4// entryType: "paint",
5// startTime: 342.160000000149,
6// duration: 0,
7// }
8// paintEntries[1] equals {
9// name: "first-contentful-paint",
10// entryType: "paint",
11// startTime: 342.160000000149,
12// duration: 0,
13// }
- getEntriesByName(entryName)按名称过滤所有条目
1const nativeLogoPerfEntry = performance.getEntriesByName('https://alligator.io/images/alligator-logo3.svg')[0];
2// It will return performance information related to the logo's performance:
3// {initiatorType: "img",
4// nextHopProtocol: "",
5// workerStart: 539.6649999311194,
6// ........
7// name: "https://alligator.io/images/alligator-logo3.svg",
8// entryType: "resource",
9// startTime: 539.5149999530986,
10// duration: 94.24000000581145
11//}
如果您正在寻找有关网站性能的更高级别信息,您也可以拨打 performance.toJSON()
。
审计您的职能
对于对特定JavaScript函数进行审核,最基本的工具是我们上面描述的performance.now()
。
以下是一個使用例子:
1const firstNow = performance.now()
2// This loop is just to simulate slow calculations
3for (let i = 0; i < 100000; i++){
4 var ii = Math.sqrt(i)
5}
6const secondNow = performance.now()
7
8const howLongDidOurLoopTake = secondNow - firstNow
9// on my laptop it returns howLongDidOurLoopTake == 4.08500000089407 in milliseconds
与现在
的问题是,如果你有许多测量,管理它有点困难. 一个更有用的工具是标记
,它会创建一些性能条目,你可以稍后查询,然后你可以结合标记并使用测量
创建新的条目。
1performance.mark('beginSquareRootLoop');
2// This loop is just to simulate slow calculations
3for (let i = 0; i < 1000000; i++){
4 var ii = Math.sqrt(i);
5}
6performance.mark('endSquareRootLoop');
7// Then anywhere in your code you can use
8
9// We create a new entry called measureSquareRootLoop which combines our two marks
10performance.measure('measureSquareRootLoop','beginSquareRootLoop', 'endSquareRootLoop');
11
12console.log(performance.getEntriesByName('beginSquareRootLoop'));
13// {detail: null,
14// name: "beginSquareRootLoop",
15// entryType: "mark",
16// startTime: 3745.360000000801,
17// duration: 0}
18
19console.log(performance.getEntriesByName('measureSquareRootLoop'));
20// {detail: null,
21// name: "measureSquareRootLoop",
22// entryType: "measure",
23// startTime: 3745.360000000801, This is the same as beginSquareRootLoop
24// duration: 9.904999984428287 shows the time it took to get from beginSquareRootLoop to endSquareRootLoop
25//}
导航数据
导航用于了解构建网页的关键步骤,访问导航数据的最安全的方式是:
1const navigationEntry = performance.getEntriesByType('navigation')[0]
在我的浏览器中,我得到:
1{
2 unloadEventStart: 213.41000002576038,
3 unloadEventEnd: 213.41000002576038,
4 domInteractive: 975.8100000326522,
5 domContentLoadedEventStart: 982.2649999987334,
6 domContentLoadedEventEnd: 1217.9650000180118,
7 domComplete: 2000.960000033956,
8 loadEventStart: 2001.044999982696,
9 loadEventEnd: 2008.6500000325032,
10 type: "reload",
11 redirectCount: 0,
12 initiatorType: "navigation",
13 nextHopProtocol: "",
14 workerStart: 2.5550000136718154,
15 redirectStart: 0,
16 redirectEnd: 0,
17 fetchStart: 2.5599999935366213,
18 domainLookupStart: 2.5599999935366213,
19 domainLookupEnd: 2.5599999935366213,
20 connectStart: 2.5599999935366213,
21 connectEnd: 2.5599999935366213,
22 secureConnectionStart: 0,
23 requestStart: 2.5599999935366213,
24 responseStart: 107.46500000823289,
25 responseEnd: 214.3950000172481,
26 transferSize: 0,
27 encodedBodySize: 0,
28 decodedBodySize: 0,
29 serverTiming: [],
30 name: "https://alligator.io/",
31 entryType: "navigation",
32 startTime: 0,
33 duration: 2008.6500000325032
34}
我们将在未来的一篇文章中详细解释如何使用这些数据,但在此期间,这里是导航时间线的可视化:
资源
每当一个资源被页面加载时,我们可以在性能条目中找到其痕迹。我们需要做的就是运行 performance.getEntriesByType('resource')
. 这包括图像,脚本,CSS文件等。
1performance.getEntriesByType('resource').filter(resource=> resource.initiatorType == 'img')
以下是Alligator.io上发现的资源之一:
1{
2 initiatorType: "img",
3 nextHopProtocol: "h2",
4 workerStart: 551.2149999849498,
5 redirectStart: 0,
6 redirectEnd: 0,
7 fetchStart: 551.3149999896996,
8 domainLookupStart: 0,
9 domainLookupEnd: 0,
10 connectStart: 0,
11 connectEnd: 0,
12 secureConnectionStart: 0,
13 requestStart: 0,
14 responseStart: 0,
15 responseEnd: 560.1850000093691,
16 transferSize: 0,
17 encodedBodySize: 0,
18 decodedBodySize: 0,
19 serverTiming: [],
20 name: "https://d33wubrfki0l68.cloudfront.net/39d2d2905588dad289b228deb021d51449f6143d/a3baf/images/logos/gatsby-logo.svg",
21 entryType: "resource",
22 startTime: 222.0450000022538,
23 duration: 338.1400000071153
24}
正如您所看到的,这个条目有许多 0 值,这是因为我们受到 CORS 的限制(这是资源时间化 API 的一个大限制)。因此,以下属性将始终返回 0: redirectStart, redirectEnd, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, and responseStart。
绘画
涂料 API 是指在窗口上绘制像素的事件。正如我们在以前的片段中所看到的那样,我们可以访问 First Time to Paint 和 First Contentful Paint. 如果您已经使用过前端优化工具,如 Lighthouse,您可能熟悉这些术语。绘画的第一个时间是第一个像素出现在用户屏幕上。第一个令人满意的涂料是当DOM中定义的元素首次渲染时。为了优化第一个令人满意的涂料,您可以减少渲染阻止的脚本和风格表,使用 HTTP 缓存,优化 JavaScript 启动和更多!
这些是有用的指标,但如果您试图了解用户所看到的内容,它们是相当有限的。
当然,寻找更新的最佳地方是Alligator.io,但如果你想真正深入探索这个话题,你应该查看Web Performance Working Group的页面(https://www.w3.org/webperf/),在那里你可以找到最新的工作草案和建议。