Skip to content

Commit b43217c

Browse files
Adam RaineDevtools-frontend LUCI CQ
authored andcommitted
[third-party] Roll web-vitals v4.2.3
This also adds a rebuild.sh script to automatically modify the code to export `attributeINP()` Bug: None Change-Id: I000c97d885a11bc0ea3d4cc4fb00418f7f9c7e61 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/5939333 Reviewed-by: Jack Franklin <[email protected]> Auto-Submit: Adam Raine <[email protected]> Commit-Queue: Adam Raine <[email protected]>
1 parent f2def9a commit b43217c

File tree

18 files changed

+95
-87
lines changed

18 files changed

+95
-87
lines changed

front_end/third_party/web-vitals/BUILD.gn

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ import("../../../scripts/build/ninja/devtools_entrypoint.gni")
66
import("../../../scripts/build/ninja/devtools_pre_built.gni")
77
import("../visibility.gni")
88

9-
EXCLUDED_SOURCES = []
9+
EXCLUDED_SOURCES = [
10+
"package/dist/web-vitals.attribution.iife.js",
11+
"package/dist/web-vitals.attribution.js",
12+
"package/dist/web-vitals.iife.js",
13+
"package/dist/web-vitals.js",
14+
]
1015

1116
SOURCES = [
1217
"package/dist/modules/attribution/deprecated.d.ts",
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
Name: Web Vitals
22
Short Name: Web Vitals
33
URL: https://github.com/GoogleChrome/web-vitals
4-
Version: 4.2.1
4+
Version: 4.2.3
55
License: Apache
66
License File: package/LICENSE
7-
Revision: d6880fdaf669735716eaf3c163baf3f2c10fefaa
7+
Revision: 9b932519b16f72328c6d8e9814b811f1bc1a0bb5
88
Security Critical: no
99
Shipped: yes
1010

1111
Description:
1212
Essential metrics for a healthy site.
1313

1414
```bash
15-
python3 scripts/deps/roll_front_end_third_party.py web-vitals web-vitals dist/modules
15+
./front_end/third_party/web-vitals/rebuild.sh
1616
```

front_end/third_party/web-vitals/package/README.md

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ The library supports all of the [Core Web Vitals](https://web.dev/articles/vital
4242

4343
- [First Contentful Paint (FCP)](https://web.dev/articles/fcp)
4444
- [Time to First Byte (TTFB)](https://web.dev/articles/ttfb)
45-
- [First Input Delay (FID)](https://web.dev/articles/fid) _Deprecated and will be removed in next major release_
45+
- [First Input Delay (FID)](https://web.dev/articles/fid)
46+
47+
> [!CAUTION]
48+
> FID is deprecated and will be removed in the next major release.
4649
4750
<a name="installation"><a>
4851
<a name="load-the-library"><a>
@@ -63,7 +66,8 @@ You can install this library from npm by running:
6366
npm install web-vitals
6467
```
6568

66-
_**Note:** If you're not using npm, you can still load `web-vitals` via `<script>` tags from a CDN like [unpkg.com](https://unpkg.com). See the [load `web-vitals` from a CDN](#load-web-vitals-from-a-cdn) usage example below for details._
69+
> [!NOTE]
70+
> If you're not using npm, you can still load `web-vitals` via `<script>` tags from a CDN like [unpkg.com](https://unpkg.com). See the [load `web-vitals` from a CDN](#load-web-vitals-from-a-cdn) usage example below for details.
6771
6872
There are a few different builds of the `web-vitals` library, and how you load the library depends on which build you want to use.
6973

@@ -81,7 +85,8 @@ onINP(console.log);
8185
onLCP(console.log);
8286
```
8387

84-
_**Note:** in version 2, these functions were named `getXXX()` rather than `onXXX()`. They've [been renamed](https://github.com/GoogleChrome/web-vitals/pull/222) in version 3 to reduce confusion (see [#217](https://github.com/GoogleChrome/web-vitals/pull/217) for details) and will continue to be available using the `getXXX()` until at least version 4. Users are encouraged to switch to the new names, though, for future compatibility._
88+
> [!NOTE]
89+
> In version 2, these functions were named `getXXX()` rather than `onXXX()`. They've [been renamed](https://github.com/GoogleChrome/web-vitals/pull/222) in version 3 to reduce confusion (see [#217](https://github.com/GoogleChrome/web-vitals/pull/217) for details) and will continue to be available using the `getXXX()` until at least version 4. Users are encouraged to switch to the new names, though, for future compatibility.
8590
8691
<a name="attribution-build"><a>
8792

@@ -213,13 +218,15 @@ In other cases, a metric callback may be called more than once:
213218
- CLS and INP should be reported any time the [page's `visibilityState` changes to hidden](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden).
214219
- All metrics are reported again (with the above exceptions) after a page is restored from the [back/forward cache](https://web.dev/articles/bfcache).
215220

216-
_**Warning:** do not call any of the Web Vitals functions (e.g. `onCLS()`, `onINP()`, `onLCP()`) more than once per page load. Each of these functions creates a `PerformanceObserver` instance and registers event listeners for the lifetime of the page. While the overhead of calling these functions once is negligible, calling them repeatedly on the same page may eventually result in a memory leak._
221+
> [!WARNING]
222+
> Do not call any of the Web Vitals functions (e.g. `onCLS()`, `onINP()`, `onLCP()`) more than once per page load. Each of these functions creates a `PerformanceObserver` instance and registers event listeners for the lifetime of the page. While the overhead of calling these functions once is negligible, calling them repeatedly on the same page may eventually result in a memory leak.
217223
218224
### Report the value on every change
219225

220226
In most cases, you only want the `callback` function to be called when the metric is ready to be reported. However, it is possible to report every change (e.g. each larger layout shift as it happens) by setting `reportAllChanges` to `true` in the optional, [configuration object](#reportopts) (second parameter).
221227

222-
_**Important:** `reportAllChanges` only reports when the **metric changes**, not for each **input to the metric**. For example, a new layout shift that does not increase the CLS metric will not be reported even with `reportAllChanges` set to `true` because the CLS metric has not changed. Similarly, for INP, each interaction is not reported even with `reportAllChanges` set to `true`—just when an interaction causes an increase to INP._
228+
> [!IMPORTANT]
229+
> `reportAllChanges` only reports when the **metric changes**, not for each **input to the metric**. For example, a new layout shift that does not increase the CLS metric will not be reported even with `reportAllChanges` set to `true` because the CLS metric has not changed. Similarly, for INP, each interaction is not reported even with `reportAllChanges` set to `true`—just when an interaction causes an increase to INP.
223230
224231
This can be useful when debugging, but in general using `reportAllChanges` is not needed (or recommended) for measuring these metrics in production.
225232

@@ -250,7 +257,8 @@ onINP(logDelta);
250257
onLCP(logDelta);
251258
```
252259

253-
_**Note:** the first time the `callback` function is called, its `value` and `delta` properties will be the same._
260+
> [!NOTE]
261+
> The first time the `callback` function is called, its `value` and `delta` properties will be the same.
254262
255263
In addition to using the `id` field to group multiple deltas for the same metric, it can also be used to differentiate different metrics reported on the same page. For example, after a back/forward cache restore, a new metric object is created with a new `id` (since back/forward cache restores are considered separate page visits).
256264

@@ -361,7 +369,8 @@ onINP(sendToGoogleAnalytics);
361369
onLCP(sendToGoogleAnalytics);
362370
```
363371

364-
_**Note:** this example relies on custom [event parameters](https://support.google.com/analytics/answer/11396839) in Google Analytics 4._
372+
> [!NOTE]
373+
> This example relies on custom [event parameters](https://support.google.com/analytics/answer/11396839) in Google Analytics 4.
365374
366375
See [Debug performance in the field](https://web.dev/articles/debug-performance-in-the-field) for more information and examples.
367376

@@ -405,14 +414,10 @@ addEventListener('visibilitychange', () => {
405414
flushQueue();
406415
}
407416
});
408-
409-
// NOTE: Safari does not reliably fire the `visibilitychange` event when the
410-
// page is being unloaded. If Safari support is needed, you should also flush
411-
// the queue in the `pagehide` event.
412-
addEventListener('pagehide', flushQueue);
413417
```
414418

415-
_**Note:** see [the Page Lifecycle guide](https://developers.google.com/web/updates/2018/07/page-lifecycle-api#legacy-lifecycle-apis-to-avoid) for an explanation of why `visibilitychange` and `pagehide` are recommended over events like `beforeunload` and `unload`._
419+
> [!NOTE]
420+
> See [the Page Lifecycle guide](https://developers.google.com/web/updates/2018/07/page-lifecycle-api#legacy-lifecycle-apis-to-avoid) for an explanation of why `visibilitychange` is recommended over events like `beforeunload` and `unload`.
416421
417422
<a name="bundle-versions"><a>
418423

@@ -580,7 +585,8 @@ interface FCPMetric extends Metric {
580585

581586
##### `FIDMetric`
582587

583-
_This interface is deprecated and will be removed in next major release_
588+
> [!CAUTION]
589+
> This interface is deprecated and will be removed in the next major release.
584590
585591
```ts
586592
interface FIDMetric extends Metric {
@@ -684,7 +690,8 @@ Calculates the [CLS](https://web.dev/articles/cls) value for the current page an
684690

685691
If the `reportAllChanges` [configuration option](#reportopts) is set to `true`, the `callback` function will be called as soon as the value is initially determined as well as any time the value changes throughout the page lifespan (Note [not necessarily for every layout shift](#report-the-value-on-every-change)).
686692

687-
_**Important:** CLS should be continually monitored for changes throughout the entire lifespan of a page—including if the user returns to the page after it's been hidden/backgrounded. However, since browsers often [will not fire additional callbacks once the user has backgrounded a page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), `callback` is always called when the page's visibility state changes to hidden. As a result, the `callback` function might be called multiple times during the same page load (see [Reporting only the delta of changes](#report-only-the-delta-of-changes) for how to manage this)._
693+
> [!IMPORTANT]
694+
> CLS should be continually monitored for changes throughout the entire lifespan of a page—including if the user returns to the page after it's been hidden/backgrounded. However, since browsers often [will not fire additional callbacks once the user has backgrounded a page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), `callback` is always called when the page's visibility state changes to hidden. As a result, the `callback` function might be called multiple times during the same page load (see [Reporting only the delta of changes](#report-only-the-delta-of-changes) for how to manage this).
688695
689696
#### `onFCP()`
690697

@@ -696,15 +703,17 @@ Calculates the [FCP](https://web.dev/articles/fcp) value for the current page an
696703

697704
#### `onFID()`
698705

699-
_This function is deprecated and will be removed in next major release_
706+
> [!CAUTION]
707+
> This function is deprecated and will be removed in the next major release.
700708
701709
```ts
702710
function onFID(callback: (metric: FIDMetric) => void, opts?: ReportOpts): void;
703711
```
704712

705713
Calculates the [FID](https://web.dev/articles/fid) value for the current page and calls the `callback` function once the value is ready, along with the relevant `first-input` performance entry used to determine the value. The reported value is a [`DOMHighResTimeStamp`](https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp).
706714

707-
_**Important:** since FID is only reported after the user interacts with the page, it's possible that it will not be reported for some page loads._
715+
> [!IMPORTANT]
716+
> Since FID is only reported after the user interacts with the page, it's possible that it will not be reported for some page loads.
708717
709718
#### `onINP()`
710719

@@ -718,7 +727,8 @@ A custom `durationThreshold` [configuration option](#reportopts) can optionally
718727

719728
If the `reportAllChanges` [configuration option](#reportopts) is set to `true`, the `callback` function will be called as soon as the value is initially determined as well as any time the value changes throughout the page lifespan (Note [not necessarily for every interaction](#report-the-value-on-every-change)).
720729

721-
_**Important:** INP should be continually monitored for changes throughout the entire lifespan of a page—including if the user returns to the page after it's been hidden/backgrounded. However, since browsers often [will not fire additional callbacks once the user has backgrounded a page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), `callback` is always called when the page's visibility state changes to hidden. As a result, the `callback` function might be called multiple times during the same page load (see [Reporting only the delta of changes](#report-only-the-delta-of-changes) for how to manage this)._
730+
> [!IMPORTANT]
731+
> INP should be continually monitored for changes throughout the entire lifespan of a page—including if the user returns to the page after it's been hidden/backgrounded. However, since browsers often [will not fire additional callbacks once the user has backgrounded a page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), `callback` is always called when the page's visibility state changes to hidden. As a result, the `callback` function might be called multiple times during the same page load (see [Reporting only the delta of changes](#report-only-the-delta-of-changes) for how to manage this).
722732
723733
#### `onLCP()`
724734

@@ -756,8 +766,8 @@ onTTFB((metric) => {
756766
});
757767
```
758768

759-
_**Note:** browsers that do not support `navigation` entries will fall back to
760-
using `performance.timing` (with the timestamps converted from epoch time to [`DOMHighResTimeStamp`](https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp)). This ensures code referencing these values (like in the example above) will work the same in all browsers._
769+
> [!NOTE]
770+
> Browsers that do not support `navigation` entries will fall back to using `performance.timing` (with the timestamps converted from epoch time to [`DOMHighResTimeStamp`](https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp)). This ensures code referencing these values (like in the example above) will work the same in all browsers.
761771
762772
### Rating Thresholds:
763773

@@ -773,7 +783,8 @@ console.log(INPThresholds); // [ 200, 500 ]
773783
console.log(LCPThresholds); // [ 2500, 4000 ]
774784
```
775785

776-
_**Note:** It's typically not necessary (or recommended) to manually calculate metric value ratings using these thresholds. Use the [`Metric['rating']`](#metric) instead._
786+
> [!NOTE]
787+
> It's typically not necessary (or recommended) to manually calculate metric value ratings using these thresholds. Use the [`Metric['rating']`](#metric) instead.
777788
778789
### Attribution:
779790

@@ -858,7 +869,8 @@ interface FCPAttribution {
858869

859870
#### `FIDAttribution`
860871

861-
_This interface is deprecated and will be removed in next major release_
872+
> [!CAUTION]
873+
> This interface is deprecated and will be removed in the next major release.
862874
863875
```ts
864876
interface FIDAttribution {
@@ -1096,7 +1108,8 @@ The primary limitation of these APIs is they have no visibility into `<iframe>`
10961108

10971109
For same-origin iframes, it's possible to use the `web-vitals` library to measure metrics, but it's tricky because it requires the developer to add the library to every frame and `postMessage()` the results to the parent frame for aggregation.
10981110

1099-
_**Note:** given the lack of iframe support, the `onCLS()` function technically measures [DCLS](https://github.com/wicg/layout-instability#cumulative-scores) (Document Cumulative Layout Shift) rather than CLS, if the page includes iframes)._
1111+
> [!NOTE]
1112+
> Given the lack of iframe support, the `onCLS()` function technically measures [DCLS](https://github.com/wicg/layout-instability#cumulative-scores) (Document Cumulative Layout Shift) rather than CLS, if the page includes iframes).
11001113
11011114
## Development
11021115

front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { INPMetric, INPMetricWithAttribution, ReportOpts } from '../types.js';
22
export declare const interactionTargetMap: Map<number, Node>;
3+
export declare const attributeINP: (metric: INPMetric) => INPMetricWithAttribution;
34
/**
45
* Calculates the [INP](https://web.dev/articles/inp) value for the current
56
* page and calls the `callback` function once the value is ready, along with
@@ -28,4 +29,3 @@ export declare const interactionTargetMap: Map<number, Node>;
2829
* during the same page load._
2930
*/
3031
export declare const onINP: (onReport: (metric: INPMetricWithAttribution) => void, opts?: ReportOpts) => void;
31-
export declare const attributeINP: (metric: INPMetric) => INPMetricWithAttribution;

front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.js

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ let pendingLoAFs = [];
3939
// that are known to not match INP are removed.
4040
let pendingEntriesGroups = [];
4141
// The `processingEnd` time of most recently-processed event, chronologically.
42-
let latestProcessingEnd;
42+
let latestProcessingEnd = 0;
4343
// A WeakMap to look up the event-timing-entries group of a given entry.
4444
// Note that this only maps from "important" entries: either the first input or
4545
// those with an `interactionId`.
@@ -139,24 +139,22 @@ const cleanupEntries = () => {
139139
});
140140
// Keep all pending LoAF entries that either:
141141
// 1) intersect with entries in the newly cleaned up `pendingEntriesGroups`
142-
// 2) occur after the most recently-processed event entry.
142+
// 2) occur after the most recently-processed event entry (for up to MAX_PREVIOUS_FRAMES)
143143
const loafsToKeep = new Set();
144144
for (let i = 0; i < pendingEntriesGroups.length; i++) {
145145
const group = pendingEntriesGroups[i];
146146
getIntersectingLoAFs(group.startTime, group.processingEnd).forEach((loaf) => {
147147
loafsToKeep.add(loaf);
148148
});
149149
}
150-
for (let i = 0; i < MAX_PREVIOUS_FRAMES; i++) {
151-
// Look at pending LoAF in reverse order so the most recent are first.
152-
const loaf = pendingLoAFs[pendingLoAFs.length - 1 - i];
153-
// If we reach LoAFs that overlap with event processing,
154-
// we can assume all previous ones have already been handled.
155-
if (!loaf || loaf.startTime < latestProcessingEnd)
156-
break;
157-
loafsToKeep.add(loaf);
158-
}
159-
pendingLoAFs = Array.from(loafsToKeep);
150+
const prevFrameIndexCutoff = pendingLoAFs.length - 1 - MAX_PREVIOUS_FRAMES;
151+
// Filter `pendingLoAFs` to preserve LoAF order.
152+
pendingLoAFs = pendingLoAFs.filter((loaf, index) => {
153+
if (loaf.startTime > latestProcessingEnd && index > prevFrameIndexCutoff) {
154+
return true;
155+
}
156+
return loafsToKeep.has(loaf);
157+
});
160158
// Reset the idle callback handle so it can be queued again.
161159
idleHandle = -1;
162160
};
Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,6 @@
11
import { MetricType, MetricRatingThresholds } from '../types.js';
2-
export declare const bindReporter: <MetricName extends "CLS" | "FCP" | "FID" | "INP" | "LCP" | "TTFB">(callback: (metric: Extract<import("../types.js").CLSMetric, {
2+
export declare const bindReporter: <MetricName extends MetricType["name"]>(callback: (metric: Extract<MetricType, {
33
name: MetricName;
4-
}> | Extract<import("../types.js").FCPMetric, {
5-
name: MetricName;
6-
}> | Extract<import("../types.js").FIDMetric, {
7-
name: MetricName;
8-
}> | Extract<import("../types.js").INPMetric, {
9-
name: MetricName;
10-
}> | Extract<import("../types.js").LCPMetric, {
11-
name: MetricName;
12-
}> | Extract<import("../types.js").TTFBMetric, {
13-
name: MetricName;
14-
}>) => void, metric: Extract<import("../types.js").CLSMetric, {
15-
name: MetricName;
16-
}> | Extract<import("../types.js").FCPMetric, {
17-
name: MetricName;
18-
}> | Extract<import("../types.js").FIDMetric, {
19-
name: MetricName;
20-
}> | Extract<import("../types.js").INPMetric, {
21-
name: MetricName;
22-
}> | Extract<import("../types.js").LCPMetric, {
23-
name: MetricName;
24-
}> | Extract<import("../types.js").TTFBMetric, {
4+
}>) => void, metric: Extract<MetricType, {
255
name: MetricName;
266
}>, thresholds: MetricRatingThresholds, reportAllChanges?: boolean) => (forceReport?: boolean) => void;

front_end/third_party/web-vitals/package/dist/modules/lib/initMetric.d.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
export declare const initMetric: <MetricName extends "CLS" | "FCP" | "FID" | "INP" | "LCP" | "TTFB">(name: MetricName, value?: number) => {
1+
import { MetricType } from '../types.js';
2+
export declare const initMetric: <MetricName extends MetricType["name"]>(name: MetricName, value?: number) => {
23
name: MetricName;
34
value: number;
45
rating: "good";
@@ -17,5 +18,5 @@ export declare const initMetric: <MetricName extends "CLS" | "FCP" | "FID" | "IN
1718
name: MetricName;
1819
}>)["entries"];
1920
id: string;
20-
navigationType: "navigate" | "reload" | "back-forward" | "back-forward-cache" | "prerender" | "restore";
21+
navigationType: "reload" | "navigate" | "prerender" | "back-forward" | "back-forward-cache" | "restore";
2122
};

front_end/third_party/web-vitals/package/dist/modules/lib/interactions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const getInteractionCountForNavigation = () => {
3434
return getInteractionCount() - prevInteractionCount;
3535
};
3636
export const resetInteractions = () => {
37-
prevInteractionCount = 0;
37+
prevInteractionCount = getInteractionCount();
3838
longestInteractionList.length = 0;
3939
longestInteractionMap.clear();
4040
};

0 commit comments

Comments
 (0)