summaryrefslogtreecommitdiff
path: root/frontend-old/node_modules/web-vitals/src/attribution/onLCP.ts
diff options
context:
space:
mode:
authoraltaf-creator <dev@altafcreator.com>2025-11-09 11:15:19 +0800
committeraltaf-creator <dev@altafcreator.com>2025-11-09 11:15:19 +0800
commit8eff962cab608341a6f2fedc640a0e32d96f26e2 (patch)
tree05534d1a720ddc3691d346c69b4972555820a061 /frontend-old/node_modules/web-vitals/src/attribution/onLCP.ts
pain
Diffstat (limited to 'frontend-old/node_modules/web-vitals/src/attribution/onLCP.ts')
-rw-r--r--frontend-old/node_modules/web-vitals/src/attribution/onLCP.ts113
1 files changed, 113 insertions, 0 deletions
diff --git a/frontend-old/node_modules/web-vitals/src/attribution/onLCP.ts b/frontend-old/node_modules/web-vitals/src/attribution/onLCP.ts
new file mode 100644
index 0000000..285f319
--- /dev/null
+++ b/frontend-old/node_modules/web-vitals/src/attribution/onLCP.ts
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {getNavigationEntry} from '../lib/getNavigationEntry.js';
+import {getSelector} from '../lib/getSelector.js';
+import {onLCP as unattributedOnLCP} from '../onLCP.js';
+import {
+ LCPAttribution,
+ LCPMetric,
+ LCPMetricWithAttribution,
+ ReportOpts,
+} from '../types.js';
+
+const attributeLCP = (metric: LCPMetric): LCPMetricWithAttribution => {
+ // Use a default object if no other attribution has been set.
+ let attribution: LCPAttribution = {
+ timeToFirstByte: 0,
+ resourceLoadDelay: 0,
+ resourceLoadDuration: 0,
+ elementRenderDelay: metric.value,
+ };
+
+ if (metric.entries.length) {
+ const navigationEntry = getNavigationEntry();
+ if (navigationEntry) {
+ const activationStart = navigationEntry.activationStart || 0;
+ const lcpEntry = metric.entries[metric.entries.length - 1];
+ const lcpResourceEntry =
+ lcpEntry.url &&
+ performance
+ .getEntriesByType('resource')
+ .filter((e) => e.name === lcpEntry.url)[0];
+
+ const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);
+
+ const lcpRequestStart = Math.max(
+ ttfb,
+ // Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
+ lcpResourceEntry
+ ? (lcpResourceEntry.requestStart || lcpResourceEntry.startTime) -
+ activationStart
+ : 0,
+ );
+ const lcpResponseEnd = Math.max(
+ lcpRequestStart,
+ lcpResourceEntry ? lcpResourceEntry.responseEnd - activationStart : 0,
+ );
+ const lcpRenderTime = Math.max(
+ lcpResponseEnd,
+ lcpEntry.startTime - activationStart,
+ );
+
+ attribution = {
+ element: getSelector(lcpEntry.element),
+ timeToFirstByte: ttfb,
+ resourceLoadDelay: lcpRequestStart - ttfb,
+ resourceLoadDuration: lcpResponseEnd - lcpRequestStart,
+ elementRenderDelay: lcpRenderTime - lcpResponseEnd,
+ navigationEntry,
+ lcpEntry,
+ };
+
+ // Only attribution the URL and resource entry if they exist.
+ if (lcpEntry.url) {
+ attribution.url = lcpEntry.url;
+ }
+ if (lcpResourceEntry) {
+ attribution.lcpResourceEntry = lcpResourceEntry;
+ }
+ }
+ }
+
+ // Use Object.assign to set property to keep tsc happy.
+ const metricWithAttribution: LCPMetricWithAttribution = Object.assign(
+ metric,
+ {attribution},
+ );
+ return metricWithAttribution;
+};
+
+/**
+ * Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and
+ * calls the `callback` function once the value is ready (along with the
+ * relevant `largest-contentful-paint` performance entry used to determine the
+ * value). The reported value is a `DOMHighResTimeStamp`.
+ *
+ * If the `reportAllChanges` configuration option is set to `true`, the
+ * `callback` function will be called any time a new `largest-contentful-paint`
+ * performance entry is dispatched, or once the final value of the metric has
+ * been determined.
+ */
+export const onLCP = (
+ onReport: (metric: LCPMetricWithAttribution) => void,
+ opts?: ReportOpts,
+) => {
+ unattributedOnLCP((metric: LCPMetric) => {
+ const metricWithAttribution = attributeLCP(metric);
+ onReport(metricWithAttribution);
+ }, opts);
+};