Skip to content

Align current Drupal page with Nuxt page commits - #538

Open
StirStudios wants to merge 4 commits into
drunomics:2.xfrom
StirStudios:fix/current-page-commit-timing
Open

StirStudios wants to merge 4 commits into
drunomics:2.xfrom
StirStudios:fix/current-page-commit-timing

Conversation

@StirStudios

@StirStudios StirStudios commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor

Problem and resulting behavior

During client navigation, Nuxt can keep the outgoing page visible while the destination resolves in Suspense. Drupal CE currently switches getPage() when the destination fetch completes, allowing shared UI to read destination Drupal data while the outgoing page is still displayed. A DancePlug reproduction observed that switch 649 ms before page:finish.

This change holds the destination key pending and promotes it on Nuxt's page:finish. SSR assignment and initial hydration remain immediate. The directly returned fetchPage() result and explicit getPage(customKey) lookups remain available without waiting for a page commit.

Navigation safeguards

  • Superseded requests can populate their own payload entry, but cannot replace pending page state, display stale messages, or follow stale redirects.
  • Application errors invalidate in-flight state and discard the pending key.
  • Aborted/duplicate navigation preserves the valid pending destination; hash-only navigation preserves its custom key.
  • Cached redirect payloads are never promoted as current pages.
  • Lifecycle setup errors are not silently swallowed.

The request version is per Nuxt application, alongside the existing page-key state; no global cross-request state or request cancellation is added.

Validation

  • Full module suite: 168 tests passed.
  • Real-browser fixture uses actual Nuxt Suspense and KeepAlive: destination fetch completes while its setup is held by a deterministic gate; both visible content and shared Drupal data stay on the origin, then switch on resolution. Returning to the cached origin and superseding a pending destination are covered.
  • Focused lifecycle tests cover out-of-order requests, errors during an in-flight fetch, cached redirects, hash-only navigation, guard aborts, duplicate navigation and cached page promotion. Three newly added regressions failed against the previous PR revision and pass with the refinement.
  • Existing CDN-shared payload/visitor URL, hydration, redirects and error suites passed.
  • Prerender checks, package build and focused ESLint passed.

Scope and compatibility

This corrects navigation timing; it does not change CDN cache keys, SSR payload migration, fetch cache keys, CMS responses, redirect targets or network request policy. The CDN-key work addresses server/browser payload identity during hydration; this PR complements it by delaying the current-page switch during navigation. No TBT improvement is claimed.

Consumers wanting destination data before commit should use the ref returned by fetchPage() or an explicit custom-key lookup. The default getPage() now retains outgoing data until page completion. The fixture covers the module's standard NuxtPage/Suspense/KeepAlive flow; it is not a guarantee for every custom nested/named NuxtPage arrangement. The consumer theme's route-snapshot protection remains a separate concern.

Nuxt 4 purges the outgoing page's data when its page component unmounts, one tick before page:finish commits the destination key. getPage() still pointed at the outgoing key and returned an empty page for that tick. Rendering never saw it, but watchers in a persistent layout did: an editor toolbar that derived its account menu key from the page cleared and refetched the menu on every navigation. getPage() now returns the fetched destination in that gap, never a redirect payload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant