1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | import {initMetric} from './lib/initMetric.js';
|
18 | import {observe, PerformanceEntryHandler} from './lib/observe.js';
|
19 | import {onHidden} from './lib/onHidden.js';
|
20 | import {onBFCacheRestore} from './lib/onBFCacheRestore.js';
|
21 | import {bindReporter} from './lib/bindReporter.js';
|
22 | import {getFCP} from './getFCP.js';
|
23 | import {ReportHandler} from './types.js';
|
24 |
|
25 |
|
26 |
|
27 | interface LayoutShift extends PerformanceEntry {
|
28 | value: number;
|
29 | hadRecentInput: boolean;
|
30 | }
|
31 |
|
32 |
|
33 | let isMonitoringFCP = false;
|
34 | let fcpValue = -1;
|
35 |
|
36 | export const getCLS = (onReport: ReportHandler, reportAllChanges?: boolean) => {
|
37 |
|
38 |
|
39 | if (!isMonitoringFCP) {
|
40 | getFCP((metric) => {
|
41 | fcpValue = metric.value;
|
42 | });
|
43 | isMonitoringFCP = true;
|
44 | }
|
45 |
|
46 | const onReportWrapped: ReportHandler = (arg) => {
|
47 | if (fcpValue > -1) {
|
48 | onReport(arg);
|
49 | }
|
50 | };
|
51 |
|
52 | let metric = initMetric('CLS', 0);
|
53 | let report: ReturnType<typeof bindReporter>;
|
54 |
|
55 | let sessionValue = 0;
|
56 | let sessionEntries: PerformanceEntry[] = [];
|
57 |
|
58 | const entryHandler = (entry: LayoutShift) => {
|
59 |
|
60 | if (!entry.hadRecentInput) {
|
61 | const firstSessionEntry = sessionEntries[0];
|
62 | const lastSessionEntry = sessionEntries[sessionEntries.length - 1];
|
63 |
|
64 |
|
65 |
|
66 |
|
67 | if (sessionValue &&
|
68 | entry.startTime - lastSessionEntry.startTime < 1000 &&
|
69 | entry.startTime - firstSessionEntry.startTime < 5000) {
|
70 | sessionValue += entry.value;
|
71 | sessionEntries.push(entry);
|
72 | } else {
|
73 | sessionValue = entry.value;
|
74 | sessionEntries = [entry];
|
75 | }
|
76 |
|
77 |
|
78 |
|
79 | if (sessionValue > metric.value) {
|
80 | metric.value = sessionValue;
|
81 | metric.entries = sessionEntries;
|
82 | report();
|
83 | }
|
84 | }
|
85 | };
|
86 |
|
87 | const po = observe('layout-shift', entryHandler as PerformanceEntryHandler);
|
88 | if (po) {
|
89 | report = bindReporter(onReportWrapped, metric, reportAllChanges);
|
90 |
|
91 | onHidden(() => {
|
92 | po.takeRecords().map(entryHandler as PerformanceEntryHandler);
|
93 | report();
|
94 | });
|
95 |
|
96 | onBFCacheRestore(() => {
|
97 | sessionValue = 0;
|
98 | fcpValue = -1;
|
99 | metric = initMetric('CLS', 0);
|
100 | report = bindReporter(onReportWrapped, metric, reportAllChanges);
|
101 | });
|
102 | }
|
103 | };
|