如何开始使用 JavaScript 性能 API

性能,性能,性能. 你可以拥有世界上最好的网站,但如果需要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 Navigation TimeLine On Alligator.io

资源

每当一个资源被页面加载时,我们可以在性能条目中找到其痕迹。我们需要做的就是运行 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/),在那里你可以找到最新的工作草案和建议。

Published At
Categories with 技术
Tagged with
comments powered by Disqus