Easily measure performance metrics in JavaScript
—
Pre-defined threshold constants for determining metric ratings according to Web Vitals standards. These thresholds classify metric values as "good", "needs improvement", or "poor" based on real-world performance data and user experience research.
Each Web Vitals metric has associated threshold constants that define the boundaries between performance ratings.
/**
* CLS thresholds: [0.1, 0.25]
* - ≤ 0.1: good
* - 0.1 - 0.25: needs improvement
* - > 0.25: poor
*/
const CLSThresholds: MetricRatingThresholds;
/**
* FCP thresholds: [1800, 3000] (milliseconds)
* - ≤ 1800ms: good
* - 1800ms - 3000ms: needs improvement
* - > 3000ms: poor
*/
const FCPThresholds: MetricRatingThresholds;
/**
* INP thresholds: [200, 500] (milliseconds)
* - ≤ 200ms: good
* - 200ms - 500ms: needs improvement
* - > 500ms: poor
*/
const INPThresholds: MetricRatingThresholds;
/**
* LCP thresholds: [2500, 4000] (milliseconds)
* - ≤ 2500ms: good
* - 2500ms - 4000ms: needs improvement
* - > 4000ms: poor
*/
const LCPThresholds: MetricRatingThresholds;
/**
* TTFB thresholds: [800, 1800] (milliseconds)
* - ≤ 800ms: good
* - 800ms - 1800ms: needs improvement
* - > 1800ms: poor
*/
const TTFBThresholds: MetricRatingThresholds;
type MetricRatingThresholds = [number, number];import {
CLSThresholds,
FCPThresholds,
INPThresholds,
LCPThresholds,
TTFBThresholds
} from "web-vitals";
// Check threshold values
console.log('CLS thresholds:', CLSThresholds); // [0.1, 0.25]
console.log('FCP thresholds:', FCPThresholds); // [1800, 3000]
console.log('INP thresholds:', INPThresholds); // [200, 500]
console.log('LCP thresholds:', LCPThresholds); // [2500, 4000]
console.log('TTFB thresholds:', TTFBThresholds); // [800, 1800]Although the Metric.rating property automatically provides ratings, you can manually calculate ratings using the thresholds:
import { LCPThresholds } from "web-vitals";
function calculateRating(value: number, thresholds: MetricRatingThresholds): string {
if (value <= thresholds[0]) {
return 'good';
} else if (value <= thresholds[1]) {
return 'needs-improvement';
} else {
return 'poor';
}
}
// Example usage
const lcpValue = 3200; // 3.2 seconds
const rating = calculateRating(lcpValue, LCPThresholds);
console.log('LCP rating:', rating); // 'needs-improvement'import { onLCP, LCPThresholds } from "web-vitals";
onLCP((metric) => {
const [goodThreshold, poorThreshold] = LCPThresholds;
console.log(`LCP: ${metric.value}ms (${metric.rating})`);
if (metric.rating === 'poor') {
const improvement = metric.value - poorThreshold;
console.log(`Need to improve by ${improvement}ms to reach 'needs-improvement'`);
} else if (metric.rating === 'needs-improvement') {
const improvement = metric.value - goodThreshold;
console.log(`Need to improve by ${improvement}ms to reach 'good'`);
}
});import {
onCLS, onFCP, onINP, onLCP, onTTFB,
CLSThresholds, FCPThresholds, INPThresholds, LCPThresholds, TTFBThresholds
} from "web-vitals";
// Monitor metrics and alert on poor performance
const thresholds = {
CLS: CLSThresholds,
FCP: FCPThresholds,
INP: INPThresholds,
LCP: LCPThresholds,
TTFB: TTFBThresholds
};
function monitorMetric(metricName: string, metric: any) {
const threshold = thresholds[metricName as keyof typeof thresholds];
if (metric.rating === 'poor') {
console.warn(`⚠️ Poor ${metricName}: ${metric.value} (threshold: >${threshold[1]})`);
// Send alert to monitoring system
sendAlert({
metric: metricName,
value: metric.value,
rating: metric.rating,
threshold: threshold[1]
});
}
}
// Set up monitoring
onCLS(metric => monitorMetric('CLS', metric));
onFCP(metric => monitorMetric('FCP', metric));
onINP(metric => monitorMetric('INP', metric));
onLCP(metric => monitorMetric('LCP', metric));
onTTFB(metric => monitorMetric('TTFB', metric));Each metric value falls into one of three categories:
The threshold values are based on:
The Web Vitals library automatically calculates and provides the rating in the metric.rating property, so manual threshold checking is typically unnecessary:
import { onLCP } from "web-vitals";
onLCP((metric) => {
// Rating is automatically calculated
console.log('LCP rating:', metric.rating); // 'good', 'needs-improvement', or 'poor'
// No need to manually check thresholds
// const rating = metric.value <= LCPThresholds[0] ? 'good' :
// metric.value <= LCPThresholds[1] ? 'needs-improvement' : 'poor';
});Threshold values may be updated in future versions of the library to reflect evolving web performance standards and user expectations. Always use the exported constants rather than hardcoding values.
import { onLCP, onCLS, onINP } from "web-vitals";
const metrics = {
lcp: null as any,
cls: null as any,
inp: null as any
};
onLCP(metric => metrics.lcp = metric);
onCLS(metric => metrics.cls = metric);
onINP(metric => metrics.inp = metric);
// Analyze overall page performance
setTimeout(() => {
const goodMetrics = Object.values(metrics)
.filter(metric => metric && metric.rating === 'good').length;
const totalMetrics = Object.values(metrics)
.filter(metric => metric !== null).length;
console.log(`Overall performance: ${goodMetrics}/${totalMetrics} metrics are good`);
}, 5000);Install with Tessl CLI
npx tessl i tessl/npm-web-vitals