Repository navigation
🐛 Prevent duplicate Next.js RUM views from discarded renders - #4940
BeltranBulbarellaDD wants to merge 16 commits into
Conversation
❌ ErrorsYour PR has failed checks. Please review the issues below and take necessary action before merging. 🚦 1 Pipeline job failed
|
Bundles Sizes Evolution
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 31857be6e6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 58fc0e9b68
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9e9ab88490
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e9c6d7cfe4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
d19f03a to
ce58867
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ce588679b4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cb890f9278
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A layout-effect redirect that returns to an already-committed pathname
(e.g. / -> /protected -> router.replace('/')) could let /protected's
stale passive effect rename the restored view, because staleness was
inferred from pathname equality, which can't tell a revisited pathname
from a fresh one.
Track a monotonic generation counter per router transition instead.
DatadogAppRouter captures the active generation at render time, and
setNextjsViewName compares it at commit time, dropping the commit if a
newer transition has since started.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e8ec37b2dc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The generation counter used to reject stale commits was a global clock not scoped to any route, so a re-render of an old, still-mounted route while a different navigation was pending could pick up a freshly-bumped generation value alongside its own stale pathname, defeating the check. Compare the commit's pathname directly against activeAppRouterPathname instead — it catches the same stale-commit cases without needing any counter. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Next.js forwards the raw href from router.push()/replace() unresolved, which can be relative to the current page (e.g. '?sort=asc' or 'details') rather than root-relative. Resolving it against window.location.origin instead of the current URL produced the wrong path for these navigations. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
setNextjsViewName compared the committed pathname (from usePathname(), which strips basePath) against activeAppRouterPathname (set from window.location.pathname, which does not). On an app with a basePath configured, these never matched, so the initial route's normalized view name was never applied. Pass window.location.pathname as the commit identity instead, keeping usePathname() only for computing the normalized view name. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 497f026c2e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Closing this one in favour of #5111 |
Fixes #4931.
Problem
DatadogAppRoutercalledstartNextjsView()during React's render phase, guarded only by auseRef. React can discard and retry a render before it commits (e.g. Suspense, concurrent interruptions). Each retry got a fresh ref, sostartNextjsView()fired again for renders that were later thrown away, creating several RUM views for one page.There was also no reliable way to tell, once a render finally committed, whether a newer navigation had already started somewhere else in the meantime. The old guard compared pathnames, which breaks when a navigation returns to a pathname it had already visited.
Goal
Start a view as soon as navigation begins (so timing is accurate even for slow routes), but only ever create or rename a view from a render that actually commits — never from one that gets discarded or superseded.
Current behavior
nextjsPlugin.onInit()starts one view immediately.onRouterTransitionStart()before React renders the new route. This starts the view right away. Query/hash-only changes and duplicate callbacks for the same transition are filtered out.DatadogAppRouter'suseEffectcallssetNextjsViewName()after React commits the route, normalizing the path (e.g./user/42->/user/[id]). Each navigation bumps a generation counter; the effect only applies its rename if that generation is still the active one when it runs. If a newer navigation has started in the meantime, the commit is dropped instead of overwriting the view that's actually displayed now.🤖 Generated with Claude Code