mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
[PR #755] [MERGED] feat: track previousNextUrl for intercepted App Router entries #819
Labels
No labels
enhancement
enhancement
good first issue
help wanted
nextjs-tracking
nextjs-tracking
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/vinext#819
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/cloudflare/vinext/pull/755
Author: @NathanDrake2406
Created: 4/2/2026
Status: ✅ Merged
Merged: 4/12/2026
Merged by: @james-elicx
Base:
main← Head:feat/layout-persistence-pr-5-previous-next-url📝 Commits (7)
c34d0a5docs: refresh stale app browser entry comments252f3d0feat: track previousNextUrl for intercepted App Router entries64342b1refactor: bind getBrowserRouterState() once in refresh case8974afbrefactor: drop dead history-state interception-context read path873cb62test(e2e): cover back/forward restoration of intercepted modal viewfae429fdocs: reword stale 'belongs to PR 5' comments96dad49fix: distinguish explicit null from undefined in previousNextUrl fallback📊 Changes
9 files changed (+323 additions, -75 deletions)
View changed files
📝
packages/vinext/src/global.d.ts(+1 -0)📝
packages/vinext/src/server/app-browser-entry.ts(+84 -58)📝
packages/vinext/src/server/app-browser-state.ts(+65 -0)📝
packages/vinext/src/shims/navigation.ts(+6 -12)📝
tests/app-browser-entry.test.ts(+102 -0)📝
tests/e2e/app-router/advanced.spec.ts(+48 -0)📝
tests/fixtures/app-basic/app/feed/@modal/(...)photos/[id]/page.tsx(+2 -0)➕
tests/fixtures/app-basic/app/feed/@modal/(...)photos/[id]/refresh-button.tsx(+13 -0)📝
tests/prefetch-cache.test.ts(+2 -5)📄 Description
Summary
Part of #726 (PR 5). This builds on PR 4's interception-aware payload IDs and cache keys by tracking
previousNextUrlin the App Router browser state. Intercepted navigations now remember the URL they came from, so refresh/back-forward behavior can distinguish soft interception from direct loads.The practical effect is that
/feed -> /photos/42modal navigations now behave correctly across the three important cases: browser reload breaks out to the full page, back/forward restores the intercepted modal view from history state, androuter.refresh()keeps the intercepted modal instead of silently switching to the direct page tree.What changed
app-browser-statenow carriespreviousNextUrlalongsideelements,interceptionContext,routeId, androotLayoutTreePath, with helpers for persisting and reading it from history state__vinext_previousNextUrlinstead of the old interception-context field, preserving the URL active before a soft navigation while keeping the existing scroll restoration state intactnavigaterecords the current URL aspreviousNextUrl,traversereconstructs interception context fromevent.state, andrefreshreconstructs it from committed router state so refresh preserves interception without changing hard-load behaviorpreviousNextUrlfrom the active history entry so full document reloads still break out of interception even though browsers preservehistory.stateacross reloadspreviousNextUrlforward so replacement navigations do not lose the source-route provenancepreviousNextUrlstate/history helpers plus E2E coverage for reload, back/forward restoration, androuter.refresh()on intercepted routes. The modal fixture now exposes a smallrouter.refresh()button to exercise the public APIapp-browser-entrycomments so they match the current dispatch/control-flow names after the refactorWhat this does NOT do
Server action interception-request parity is still intentionally deferred. This PR preserves the browser-side
previousNextUrlstate during server-action merges, but it does not add interception headers to the action POST itself.Test plan
vp test run tests/app-browser-entry.test.tsvp test run tests/app-router.test.tsvp run test:e2e tests/e2e/app-router/advanced.spec.ts --grep 'hard reload after intercepted navigation renders the full page|back then forward restores intercepted modal view|router.refresh preserves intercepted modal view'git commitpre-commit hook (vp check --fix)🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.