-
Notifications
You must be signed in to change notification settings - Fork 30.2k
Description
Link to the code that reproduces this issue
https://github.com/glifchits/next-cwv-pages-router-repro
To Reproduce
- Build a Next.js pages router application and implement
useReportWebVitalsfollowing instructions in the documentation (code in repro repository) - Observe the emitted CWV events, paying attention to the events emitted after a soft navigation ("client-side navigation" as implemented by
next/link)
Current vs. Expected behavior
Current: after a pages router soft navigation, useReportWebVitals emits duplicate metrics such as LCP, TTFB, etc.
Expected: soft navigations do not cause metrics to be emitted by default. Particularly not with values that duplicate the first emitted metric values.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 24.5.0: Tue Apr 22 19:54:49 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T6000
Available memory (MB): 32768
Available CPU cores: 10
Binaries:
Node: 22.1.0
npm: 10.7.0
Yarn: 1.22.22
pnpm: 10.2.0
Relevant Packages:
next: 15.3.2 // Latest available version is detected (15.3.2).
eslint-config-next: 15.3.2
react: 19.1.0
react-dom: 19.1.0
typescript: 5.8.3
Next.js Config:
output: N/AWhich area(s) are affected? (Select all that apply)
Instrumentation
Which stage(s) are affected? (Select all that apply)
next dev (local), next build (local), next start (local), Other (Deployed)
Additional context
CWV on soft navigations are experimental and there's a case to be made for opting-in to the experimental measurement, however the duplicate measurements seem like the bigger issue, as this could bias production RUM measurements.
I have tested this in app router, and following the documentation (adding a client component to the root layout), it seems to be working aligned with my expectation. So this seems like a bug with how the hook behaves in pages router.
In our pages router implementation of CWV tracking, we add a function that's executed in the client runtime on the global scope of _app.tsx and this seems to produce the expected behaviour I described above. So long as my understanding of the CWV reporting behaviour is accurate, I'm not sure if a React hook is the correct API for pages router, and perhaps the docs should recommend a different approach.