Easily measure performance metrics in JavaScript
npx @tessl/cli install tessl/npm-web-vitals@5.1.0Web Vitals is a tiny (~2K, brotli'd), modular library for measuring all the Web Vitals metrics on real users, in a way that accurately matches how they're measured by Chrome and reported to other Google tools. It supports all Core Web Vitals and additional performance metrics, with both standard measurement and attribution builds for detailed performance debugging.
npm install web-vitalsimport { onCLS, onFCP, onINP, onLCP, onTTFB } from "web-vitals";For attribution build (includes debugging information):
import { onCLS, onFCP, onINP, onLCP, onTTFB } from "web-vitals/attribution";For CommonJS:
const { onCLS, onFCP, onINP, onLCP, onTTFB } = require("web-vitals");Individual module imports:
import { onCLS } from "web-vitals/onCLS.js";
import { onFCP } from "web-vitals/onFCP.js";
import { onINP } from "web-vitals/onINP.js";
import { onLCP } from "web-vitals/onLCP.js";
import { onTTFB } from "web-vitals/onTTFB.js";Attribution build individual modules:
import { onCLS } from "web-vitals/attribution/onCLS.js";
import { onFCP } from "web-vitals/attribution/onFCP.js";
import { onINP } from "web-vitals/attribution/onINP.js";
import { onLCP } from "web-vitals/attribution/onLCP.js";
import { onTTFB } from "web-vitals/attribution/onTTFB.js";import { onCLS, onFCP, onINP, onLCP, onTTFB } from "web-vitals";
// Measure Core Web Vitals
onCLS((metric) => {
console.log('CLS:', metric.value, metric.rating);
});
onINP((metric) => {
console.log('INP:', metric.value, metric.rating);
});
onLCP((metric) => {
console.log('LCP:', metric.value, metric.rating);
});
// Measure Other Web Vitals
onFCP((metric) => {
console.log('FCP:', metric.value, metric.rating);
});
onTTFB((metric) => {
console.log('TTFB:', metric.value, metric.rating);
});Web Vitals is built around several key components:
onCLS, onFCP, onINP, onLCP, onTTFB)Functions to measure the three Core Web Vitals metrics that are part of Google's page experience signals.
function onCLS(callback: (metric: CLSMetric) => void, opts?: ReportOpts): void;
function onINP(callback: (metric: INPMetric) => void, opts?: INPReportOpts): void;
function onLCP(callback: (metric: LCPMetric) => void, opts?: ReportOpts): void;Functions to measure additional Web Vitals metrics useful for performance monitoring and debugging.
function onFCP(callback: (metric: FCPMetric) => void, opts?: ReportOpts): void;
function onTTFB(callback: (metric: TTFBMetric) => void, opts?: ReportOpts): void;Enhanced measurement functions that include detailed attribution data for performance debugging and optimization.
function onCLS(callback: (metric: CLSMetricWithAttribution) => void, opts?: AttributionReportOpts): void;
function onINP(callback: (metric: INPMetricWithAttribution) => void, opts?: INPAttributionReportOpts): void;
function onLCP(callback: (metric: LCPMetricWithAttribution) => void, opts?: AttributionReportOpts): void;
function onFCP(callback: (metric: FCPMetricWithAttribution) => void, opts?: AttributionReportOpts): void;
function onTTFB(callback: (metric: TTFBMetricWithAttribution) => void, opts?: AttributionReportOpts): void;Pre-defined threshold values for determining metric ratings according to Web Vitals standards.
const CLSThresholds: MetricRatingThresholds;
const FCPThresholds: MetricRatingThresholds;
const INPThresholds: MetricRatingThresholds;
const LCPThresholds: MetricRatingThresholds;
const TTFBThresholds: MetricRatingThresholds;interface Metric {
/** The name of the metric (in acronym form) */
name: 'CLS' | 'FCP' | 'INP' | 'LCP' | 'TTFB';
/** The current value of the metric */
value: number;
/** The rating as to whether the metric value is within thresholds */
rating: 'good' | 'needs-improvement' | 'poor';
/** The delta between current and last-reported value */
delta: number;
/** A unique ID representing this particular metric instance */
id: string;
/** Any performance entries relevant to the metric value calculation */
entries: PerformanceEntry[];
/** The type of navigation */
navigationType: 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender' | 'restore';
}
interface ReportOpts {
/** Whether to report all metric changes or just final values */
reportAllChanges?: boolean;
}
interface INPReportOpts extends ReportOpts {
/** Minimum duration threshold for INP interactions */
durationThreshold?: number;
}
interface AttributionReportOpts extends ReportOpts {
/** Custom function to generate target selectors for DOM elements */
generateTarget?: (el: Node | null) => string | undefined;
}
interface INPAttributionReportOpts extends AttributionReportOpts {
/** Minimum duration threshold for INP interactions */
durationThreshold?: number;
}
type MetricRatingThresholds = [number, number];