Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Can we optimise this script to handle submission of metrics in SPAs

24 views
Skip to first unread message

Basit Qayoom

unread,
Aug 12, 2024, 8:49:53 AM8/12/24
to web-vitals-feedback
import { onLCP, onINP, onCLS, onTTFB, onFCP, Metric } from "web-vitals";

/**
* Represents a timestamp with milliseconds and date.
*
* @interface Timestamp
*/
interface Timestamp {
/**
* The timestamp in milliseconds.
*
* @type {number}
*/
milliseconds: number;

/**
* The timestamp as a Date object.
*
* @type {Date}
*/
date: Date;
}

/**
* Represents the data returned from web vitals metrics.
*
* @interface ReturnedData
*/
interface ReturnedData {
/**
* An array of web vitals metrics.
*
* @type {Metric[]}
*/
data: Metric[];

/**
* The timestamp when the data was collected.
*
* @type {?Timestamp}
*/
timestamp?: Timestamp;

/**
* The location of the page where metrics were collected.
*
* @type {?Location}
*/
location?: Location;
}

/**
* The key used to store web vitals data in local storage.
*
* @type {string}
*/
const LOCAL_STORAGE_KEY = "pw-web-vitals";

/**
* The expiration time for the stored data in milliseconds.
*
* @type {number}
*/
const EXPIRATION_TIME_MS = 1 * 60 * 1000; // 1 minute in milliseconds

// Initialize returnedData properly
/**
* The data structure to store collected web vitals metrics.
*
* @type {ReturnedData}
*/
const returnedData: ReturnedData = {
data: [], // Ensure data is initialized as an array
};

// Handle web vitals metrics
/**
* Handles a web vitals metric by adding it to the returnedData if not already present.
*
* @param {Metric} metric - The web vitals metric to handle.
*/
const handleMetric = (metric: Metric) => {
const { data } = returnedData;

// Initialize location only once
if (!returnedData.location) {
returnedData.location = { ...window.location };
}

// Add new metric if it doesn't already exist and the array length is less than 5
if (
!data.some((existingMetric) => existingMetric.name === metric.name) &&
data.length < 5
) {
data.push(metric);
}

// Update the timestamp and store in local storage if 5 metrics are collected
if (data.length === 5) {
returnedData.timestamp = {
milliseconds: Date.now(),
date: new Date(),
};

saveWebVitalsData();
// send to endpoint
}

// Log the updated returnedData
console.log(returnedData);
};

// Save web vitals data to local storage
/**
* Saves the web vitals data to local storage.
*/
const saveWebVitalsData = () => {
const currentPath = returnedData.location!.pathname;
const timestamp = returnedData.timestamp!.milliseconds;

const storedDataString = localStorage.getItem(LOCAL_STORAGE_KEY);
const webVitalsData: { [path: string]: number } = storedDataString
? JSON.parse(storedDataString)
: {};

// Update or add entry for the current path
webVitalsData[currentPath] = timestamp;

localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(webVitalsData));
};

// Main function to start monitoring metrics
/**
* Starts monitoring web vitals metrics.
*/
function main() {
onCLS(handleMetric);
onFCP(handleMetric);
onLCP(handleMetric);
onTTFB(handleMetric);
onINP(handleMetric);
}

// Initialize monitoring based on local storage data
/**
* Initializes monitoring based on the data stored in local storage.
*/
function initializeMonitoring() {
if (typeof window !== "undefined") {
const webVitalsDataString = localStorage.getItem(LOCAL_STORAGE_KEY);

try {
if (!webVitalsDataString) {
main();
return;
}

const webVitalsData: { [path: string]: number } =
JSON.parse(webVitalsDataString);
const currentPath = window.location.pathname;
const timestamp = webVitalsData[currentPath];

if (timestamp) {
// Check if data is expired
if (Date.now() - timestamp > EXPIRATION_TIME_MS) {
// Remove the expired data
delete webVitalsData[currentPath];
localStorage.setItem(
LOCAL_STORAGE_KEY,
JSON.stringify(webVitalsData)
);

// Start monitoring metrics
main();
}
} else {
// No data for current path, start monitoring metrics
main();
}
} catch (error) {
console.error("Error handling web vitals data:", error);
main();
}
}
}

export { initializeMonitoring };

Barry Pollard

unread,
Aug 12, 2024, 9:01:18 AM8/12/24
to Basit Qayoom, web-vitals-feedback
The Web Vitals currently cannot be measured for soft navigation as used by SPAs.

Chrome is currently experimenting with ways of enabling this, which are detailed in this post:
https://developer.chrome.com/docs/web-platform/soft-navigations-experiment

This can be enabled with the chrome://flags/#enable-experimental-web-platform-features flag.

Thanks,
Barry


--
You received this message because you are subscribed to the Google Groups "web-vitals-feedback" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web-vitals-feed...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/web-vitals-feedback/db0c85d4-edfc-4391-8e35-fcba5190ce22n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages