Repository navigation
Conversation
53c97f7 to
10bc6d6
Compare
size-limit report 📦
|
| name: string, | ||
| nodes: Node[] | undefined, | ||
| attributions?: WebVitalData['attributions'], | ||
| time = metric.value, |
There was a problem hiding this comment.
q: Can't we set this inside this function? It seem we set INP and CLS both the "last entry", but they are both setting it to metric.entries[metric.entries.length - 1]?.startTime ?? 0. Couldn't this be potentially:
const time = metric.entries[metric.entries.length - 1] ?? metric.valueIt is a different logic than the current implemented, but asking since LCP doesn't make use of the "last entry". If LCP shouldn't make use of it, maybe we should document when this should be overwritten
There was a problem hiding this comment.
m: +1, LCP's last entry startTime is its render time, so it works there too. metric.value is wrong as a time for soft navs, prerender and bfcache.
For bfcache there are no entries, so we could fall back to the navigation start:
const lastEntry = metric.entries[metric.entries.length - 1];
const time = lastEntry?.startTime ?? (metric.navigationStartTime ?? 0) + metric.value;This also would put a CLS of 0 on its soft nav which is correct.
There was a problem hiding this comment.
Good points, thanks! I went with your suggestion @logaretm
| // The CLS value is a score, not a time, so we place the event at the last layout shift. A CLS of 0 has no layout | ||
| // shift, so it goes at the time origin. | ||
| const lastEntry = metric.entries[metric.entries.length - 1]; | ||
| return getWebVital(metric, 'cumulative-layout-shift', nodes, layoutShifts, lastEntry?.startTime ?? 0); |
There was a problem hiding this comment.
l: a soft nav with a CLS of 0 lands at page load here.
metric.navigationStartTime ?? 0 would put it on its navigation, like _sendClsSpan does.
There was a problem hiding this comment.
Good catch, thx! Went with the suggestion.
| name: string, | ||
| nodes: Node[] | undefined, | ||
| attributions?: WebVitalData['attributions'], | ||
| time = metric.value, |
There was a problem hiding this comment.
m: +1, LCP's last entry startTime is its render time, so it works there too. metric.value is wrong as a time for soft navs, prerender and bfcache.
For bfcache there are no entries, so we could fall back to the navigation start:
const lastEntry = metric.entries[metric.entries.length - 1];
const time = lastEntry?.startTime ?? (metric.navigationStartTime ?? 0) + metric.value;This also would put a CLS of 0 on its soft nav which is correct.
10bc6d6 to
e7aa72f
Compare
e7aa72f to
1825836
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1825836. Configure here.
3c0856f to
ddb99d3
Compare
ddb99d3 to
1ae96f8
Compare
1ae96f8 to
47e4946
Compare
47e4946 to
4a8b3bc
Compare
7b429e3 to
c94f742
Compare
The replay CLS event used the CLS score as its timestamp, so it always landed a fraction of a millisecond after page load. Use the start time of the last layout shift instead, like the CLS span in tracing does. This also picks the time origin from when the shift happened. Co-Authored-By: Claude <noreply@anthropic.com>
Like CLS, the replay INP event used the metric value as its timestamp. For INP that value is a duration, so the event landed shortly after page load. Use the start time of the interaction instead. Co-Authored-By: Claude <noreply@anthropic.com>
Soft navigation and bfcache metrics are relative to the start of their navigation, not the document time origin. A CLS of 0 or a bfcache LCP has no entry to place the event at, so it landed at page load. Fall back to the navigation start plus the value instead, like tracing does. All three vitals now share this logic in getWebVital. LCP also uses its last entry now, which is the render time, so a soft navigation LCP is no longer placed relative to page load. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
f867ef9 to
c43e986
Compare

The Replay integration adding web vital breadcrumbs used the metric value as the timestamp for CLS and INP web vitals. This is incorrect because that value is a score for CLS and a duration for INP, so both events always landed just after page load. This was a pre-existing bug, but it showed up during work on #23054. With this PR, CLS goes at the last layout shift and INP at the interaction, like we already do with spans in tracing. Both also get the time origin from when that happened, so they stay correct after a clock drift correction. A CLS of 0 has no layout shift, so it stays at the start of its navigation