{"id":12655,"library":"web-vitals","title":"Web Vitals Measurement Library","description":"The `web-vitals` library provides a lightweight, modular way to measure essential performance metrics, known as Web Vitals, directly in the browser. It focuses on the current Core Web Vitals (Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS)), as well as First Contentful Paint (FCP) and Time to First Byte (TTFB). Maintained by the Google Chrome team, this library ensures that the collected data accurately reflects how these metrics are measured by Chrome and reported in official Google tools like the Chrome User Experience Report. It is widely used for Real User Monitoring (RUM) to collect and send performance data to analytics endpoints. The library is actively developed, with its current stable version being 5.2.0, and releases generally align with updates to Web Vitals definitions and Chrome's underlying measurement methodologies.","status":"active","version":"5.2.0","language":"javascript","source_language":"en","source_url":"https://github.com/GoogleChrome/web-vitals","tags":["javascript","crux","performance","metrics","Core Web Vitals","CLS","FCP","INP","LCP","typescript"],"install":[{"cmd":"npm install web-vitals","lang":"bash","label":"npm"},{"cmd":"yarn add web-vitals","lang":"bash","label":"yarn"},{"cmd":"pnpm add web-vitals","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Primary named exports for Core Web Vitals metrics. CommonJS `require` is not officially supported for modern versions, prefer ESM imports.","wrong":"const { onLCP } = require('web-vitals');","symbol":"onLCP, onINP, onCLS","correct":"import { onLCP, onINP, onCLS } from 'web-vitals';"},{"note":"Additional named exports for other key Web Vitals. All functions are named exports from the main package.","wrong":"import onFCP from 'web-vitals/onFCP';","symbol":"onFCP, onTTFB","correct":"import { onFCP, onTTFB } from 'web-vitals';"},{"note":"The 'attribution' build provides richer diagnostic data for debugging poor scores, imported from a specific subpath. Only use this if you need the extra data as it has a slightly larger bundle size.","wrong":"import { onLCP } from 'web-vitals';","symbol":"onLCP, onINP, onCLS (Attribution build)","correct":"import { onLCP, onINP, onCLS } from 'web-vitals/attribution';"}],"quickstart":{"code":"import { onCLS, onFCP, onINP, onLCP, onTTFB, type Metric } from 'web-vitals';\n\ninterface AnalyticsData {\n  name: string;\n  value: number;\n  id: string;\n  navigationType: string;\n  delta?: number;\n  entries?: PerformanceEntry[];\n}\n\nfunction sendToAnalytics(metric: Metric) {\n  const analyticsEndpoint = process.env.ANALYTICS_URL ?? '/api/analytics';\n  const data: AnalyticsData = {\n    name: metric.name,\n    value: metric.value,\n    id: metric.id,\n    navigationType: metric.navigationType,\n    delta: metric.delta,\n    entries: metric.entries // Include entries for detailed analysis if needed\n  };\n\n  // Use sendBeacon for reliable reporting on page unload\n  (navigator.sendBeacon && navigator.sendBeacon(analyticsEndpoint, JSON.stringify(data))) ||\n  fetch(analyticsEndpoint, {\n    body: JSON.stringify(data),\n    method: 'POST',\n    credentials: 'omit',\n    keepalive: true, // Ensures request completes even if page unloads\n    headers: {\n      'Content-Type': 'application/json'\n    }\n  }).catch(error => console.error('Failed to send analytics:', error));\n\n  console.log(`Metric Reported: ${metric.name} - Value: ${metric.value} (ID: ${metric.id})`);\n}\n\n// Measure all Core Web Vitals and other key metrics, sending them to analytics\nonCLS(sendToAnalytics);\nonFCP(sendToAnalytics);\nonINP(sendToAnalytics);\nonLCP(sendToAnalytics);\nonTTFB(sendToAnalytics);\n\nconsole.log('Web Vitals measurement initialized.');","lang":"typescript","description":"This code demonstrates how to import and use `web-vitals` to measure all standard metrics (CLS, FCP, INP, LCP, TTFB) and send them to a hypothetical analytics endpoint using `navigator.sendBeacon` or `fetch` with `keepalive` for robust reporting."},"warnings":[{"fix":"Replace all calls to `onFID()` with `onINP()`. The `onINP()` function takes the same `reportCallback` signature.","message":"The `onFID()` function was deprecated in v3/v4 and completely removed in v5. It has been superseded by `onINP()` (Interaction to Next Paint) as the primary responsiveness metric in Core Web Vitals as of March 2024.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Migrate from `getXXX()` functions to their `onXXX()` counterparts (e.g., `getCLS` to `onCLS`). Ensure your analytics reporting handles multiple metric updates, especially for CLS and INP which can change over time.","message":"All `getXXX()` functions (e.g., `getCLS`, `getLCP`) were deprecated in v3 and removed in v4. These functions were designed for one-off measurement, whereas the `onXXX()` functions provide more accurate real-time field data by reporting updates throughout the page lifecycle.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Review your target browser support matrix. If you need to support very old or niche browsers, you might need to stick to an earlier `web-vitals` version or implement custom polyfills for certain `PerformanceObserver` APIs.","message":"The browser support policy changed in v5 to 'Baseline Widely available', potentially impacting older browser versions. This means features are supported in browsers that have 95% or greater global usage for at least 6 months.","severity":"breaking","affected_versions":">=5.0.0"},{"fix":"Update your analytics processing or UI code to reflect the new property names in the attribution data if you are consuming detailed diagnostic information. Refer to the `upgrading-to-v4.md` and `upgrading-to-v5.md` guides in the GitHub repository for a complete list of changes.","message":"When using the `/attribution` build, several fields within the attribution objects for LCP, INP, and TTFB metrics were renamed in v4 and v5. For example, `eventTarget` to `interactionTarget` for INP, and various `*Time` fields to `*Duration` for LCP/TTFB.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Implement a robust analytics reporting strategy. It's recommended to send the final metric value and any delta upon the `pagehide` event or when the page's visibility state changes to hidden, using `navigator.sendBeacon` for reliability. The library examples demonstrate this pattern.","message":"Metrics like CLS and INP can update multiple times throughout the page's lifecycle. The `onXXX()` functions will call your callback whenever the metric's value changes or is finalized. Ensure your analytics integration is designed to handle these updates, potentially reporting the latest value (or delta) upon page unload or visibility change.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure `web-vitals` is only imported and executed in a browser context. If using a server-side rendering (SSR) framework, conditionally import or execute the `web-vitals` code only on the client side (e.g., inside `useEffect` in React, or within `window.onload` checks).","cause":"The `web-vitals` library relies on browser-specific APIs (like `document`, `window`, `PerformanceObserver`) and is not intended to run in Node.js environments.","error":"ReferenceError: document is not defined"},{"fix":"Update your code to use `onINP` instead of `onFID`. You may also need to upgrade your `web-vitals` package to a version that supports `onINP` if you are on a very old version (though `onINP` has been present for a while).","cause":"You are attempting to use the `onFID` function which was removed in `web-vitals` v5.0.0. Interaction to Next Paint (INP) replaced First Input Delay (FID) as a Core Web Vital.","error":"TypeError: onFID is not a function"},{"fix":"Implement a `sendToAnalytics` function (as shown in the quickstart example) and pass it to each `onXXX` function. Ensure this function correctly formats and dispatches the data to your analytics provider (e.g., Google Analytics, custom API) and that the endpoint is reachable and correctly configured to receive the data. Consider using `navigator.sendBeacon` for improved reliability.","cause":"The `web-vitals` library measures metrics but does not send them to an analytics service by itself. You must provide a callback function that sends the collected `Metric` object to your chosen analytics endpoint.","error":"Web Vitals metrics are not appearing in my analytics dashboard."}],"ecosystem":"npm"}