nextjs - 💡(How to fix) Fix useReportWebVitals does not reliably surface CLS/INP in App or Pages Router with documented setup [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#90952Fetched 2026-04-08 00:19:10
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Timeline (top)
closed ×1commented ×1labeled ×1locked ×1

Error Message

  • Following docs, all listed metrics should be observable in common local verification flows, or docs should clearly warn about finalization behavior and timing constraints.

Code Example

Operating System:
  Platform: darwin
  Arch: arm64
  Version: unknown
  Available memory (MB): 36864
  Available CPU cores: 11
Binaries:
  Node: 24.3.0
  npm: 10.8.2
  Yarn: 1.22.22
  pnpm: N/A
Relevant Packages:
  next: 16.1.6 // Latest available version is detected (16.1.6).
  eslint-config-next: 16.1.6
  react: 19.2.3
  react-dom: 19.2.3
  typescript: 5.9.3
Next.js Config:
  output: N/A
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

App Router repro: https://github.com/jenewland1999/nextjs-web-vitals-repro-app-router

Pages Router repro: https://github.com/jenewland1999/nextjs-web-vitals-repro-pages-router

To Reproduce

  1. Clone and run the App Router repro:
    • git clone https://github.com/jenewland1999/nextjs-web-vitals-repro-app-router
    • cd nextjs-web-vitals-repro-app-router && bun install && bun run dev
  2. Open http://localhost:3000 in Chrome.
  3. Hard refresh while tab is visible.
  4. Do not interact for ~3 seconds (CLS triggers are automatic in the page).
  5. Click Trigger slow interaction (INP) a few times.
  6. Hide the tab or reload once to force final metric finalization.
  7. Compare emitted metrics in the table/console:
    • app-hook (from useReportWebVitals)
    • fallback (enable toggle: Enable fallback observers (web-vitals))
  8. Repeat the same flow for the Pages Router repro:
    • git clone https://github.com/jenewland1999/nextjs-web-vitals-repro-pages-router
    • cd nextjs-web-vitals-repro-pages-router && bun install && bun run dev
  9. In Pages repro, also navigate / -> /about -> / to observe Pages custom metrics.
  10. Repeat in production mode for both repos:
    • bun run build && bun run start

Current vs. Expected behavior

Current behavior:

  • FCP/TTFB/LCP/FID often appear.
  • CLS and/or INP may be missing in normal local testing unless specific page-hide/finalization timing occurs.
  • With a direct web-vitals fallback (onCLS/onINP with explicit options), these metrics are observable more consistently.

Expected behavior:

  • Following docs, all listed metrics should be observable in common local verification flows, or docs should clearly warn about finalization behavior and timing constraints.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: unknown
  Available memory (MB): 36864
  Available CPU cores: 11
Binaries:
  Node: 24.3.0
  npm: 10.8.2
  Yarn: 1.22.22
  pnpm: N/A
Relevant Packages:
  next: 16.1.6 // Latest available version is detected (16.1.6).
  eslint-config-next: 16.1.6
  react: 19.2.3
  react-dom: 19.2.3
  typescript: 5.9.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

  • Performance
  • Pages Router
  • Runtime

Which stage(s) are affected? (Select all that apply)

  • next dev (local)
  • next build (local)
  • next start (local)

Additional context

Notes from source inspection:

  • Next.js currently wires useReportWebVitals directly to onCLS/onINP/onLCP/... with default options:
    • packages/next/src/client/web-vitals.ts
  • It does not expose options to callers (for example reportAllChanges, INP threshold tuning).
  • Next.js currently depends on web-vitals: 4.2.1:
    • packages/next/package.json

Observed mismatch risk:

  • Docs list all web vitals as included, but do not strongly call out CLS/INP finalization/timing caveats in the same API flow:
    • docs/01-app/03-api-reference/04-functions/use-report-web-vitals.mdx

Related evidence from upstream web-vitals changelog/issues:

Suggested fixes

  1. Expose optional config through useReportWebVitals (or a companion API), e.g.:
    • reportAllChanges
    • durationThreshold for INP
  2. Upgrade Next.js bundled web-vitals from 4.2.1 to current v5 line (or document rationale for staying on v4).
  3. Strengthen Next.js E2E coverage for this API:
    • assert specific metric names (CLS, INP), not only total event count.
  4. Update docs with explicit caveats:
    • CLS/INP may finalize on page hide/visibility transitions.
    • local verification guidance for reliable observation.

Repro implementation notes

  • Both repros use the documented useReportWebVitals integration for their router type.
  • Both repros include an optional fallback toggle (web-vitals direct observers) to compare hook vs fallback emissions.
  • Both repros include intentional CLS and INP triggers to make metric collection easier to verify.

Canary verification update

Both public repro repositories have now been updated and verified on [email protected]:

Both still reproduce the issue in local testing (next dev and next build && next start).

extent analysis

Quick Fix Summary

The missing CLS and INP values are caused by two things:

  1. Next.js bundles an old web‑[email protected] that finalises CLS/INP only on a visibility‑change event.
  2. The useReportWebVitals hook does not expose the newer options (reportAllChanges, durationThreshold, etc.) that the v5 library needs to emit those metrics reliably.

Solution – upgrade the bundled web‑vitals to v5 (or alias to a newer version) and wrap the library yourself so you can pass the needed options. The wrapper can be used exactly like the built‑in hook, so no app‑code changes are required beyond the import.


Step‑by‑Step Fix Plan

1. Upgrade / alias web-vitals to v5

If you are using Bun, npm, pnpm or yarn, add a resolution/override that forces the newer version.

# npm / bun
npm i -D web-vitals@^5.2.0
# or with bun
bun add -D web-vitals@^5.2.0

# yarn (v1)
yarn add -D web-vitals@^5.2.0
# add a "resolutions" field in package.json
# {
#   "resolutions": { "web-vitals": "^5.2.0" }
# }

# pnpm
pnpm add -D web-vitals@^5.2.0
# pnpm overrides in package.json
# {
#   "pnpm": { "overrides": { "web-vitals

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING