this repo has no description
1import { bindReporter } from './lib/bindReporter.js';
2import { initMetric } from './lib/initMetric.js';
3import { observe } from './lib/observe.js';
4import { onHidden } from './lib/onHidden.js';
5
6/*
7 * Copyright 2020 Google LLC
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * https://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22/**
23 * Calculates the [CLS](https://web.dev/cls/) value for the current page and
24 * calls the `callback` function once the value is ready to be reported, along
25 * with all `layout-shift` performance entries that were used in the metric
26 * value calculation. The reported value is a `double` (corresponding to a
27 * [layout shift score](https://web.dev/cls/#layout-shift-score)).
28 *
29 * If the `reportAllChanges` configuration option is set to `true`, the
30 * `callback` function will be called as soon as the value is initially
31 * determined as well as any time the value changes throughout the page
32 * lifespan.
33 *
34 * _**Important:** CLS should be continually monitored for changes throughout
35 * the entire lifespan of a page—including if the user returns to the page after
36 * it's been hidden/backgrounded. However, since browsers often [will not fire
37 * additional callbacks once the user has backgrounded a
38 * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden),
39 * `callback` is always called when the page's visibility state changes to
40 * hidden. As a result, the `callback` function might be called multiple times
41 * during the same page load._
42 */
43const onCLS = (onReport) => {
44 const metric = initMetric('CLS', 0);
45 let report;
46
47 let sessionValue = 0;
48 let sessionEntries = [];
49
50 // const handleEntries = (entries: Metric['entries']) => {
51 const handleEntries = (entries) => {
52 entries.forEach(entry => {
53 // Only count layout shifts without recent user input.
54 if (!entry.hadRecentInput) {
55 const firstSessionEntry = sessionEntries[0];
56 const lastSessionEntry = sessionEntries[sessionEntries.length - 1];
57
58 // If the entry occurred less than 1 second after the previous entry and
59 // less than 5 seconds after the first entry in the session, include the
60 // entry in the current session. Otherwise, start a new session.
61 if (
62 sessionValue &&
63 sessionEntries.length !== 0 &&
64 entry.startTime - lastSessionEntry.startTime < 1000 &&
65 entry.startTime - firstSessionEntry.startTime < 5000
66 ) {
67 sessionValue += entry.value;
68 sessionEntries.push(entry);
69 } else {
70 sessionValue = entry.value;
71 sessionEntries = [entry];
72 }
73
74 // If the current session value is larger than the current CLS value,
75 // update CLS and the entries contributing to it.
76 if (sessionValue > metric.value) {
77 metric.value = sessionValue;
78 metric.entries = sessionEntries;
79 if (report) {
80 report();
81 }
82 }
83 }
84 });
85 };
86
87 const po = observe('layout-shift', handleEntries);
88 if (po) {
89 report = bindReporter(onReport, metric);
90
91 const stopListening = () => {
92 handleEntries(po.takeRecords() );
93 report(true);
94 };
95
96 onHidden(stopListening);
97
98 return stopListening;
99 }
100
101 return;
102};
103
104export { onCLS };
105//# sourceMappingURL=getCLS.js.map