mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
[PR #753] [MERGED] feat: encode interception context in App Router payload IDs and caches #817
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#817
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/753
Author: @NathanDrake2406
Created: 4/2/2026
Status: ✅ Merged
Merged: 4/11/2026
Merged by: @james-elicx
Base:
main← Head:feat/layout-persistence-pr-4-interception-encoding📝 Commits (10+)
2a675eftest: add E2E verification for layout persistence flat payload pipeline070cef3test: harden layout persistence hydration assertionse0af07ctest: address layout-persistence spec gaps1f0f798test: tighten not.toBeAttached() assertions for absent elementsdda8accchore: trigger CIe89983bfeat: encode interception context in App Router payload IDs and caches6c7ab94test: update App Router entry snapshots for interception encoding328e9bcfix: reuse committed interception context for soft navigationsc2a5555chore: fix formatting in app-browser-entry after rebase43dcea9fix: update mounted-slot test helper calls for 4-arg createResolvedElements signature📊 Changes
19 files changed (+624 additions, -117 deletions)
View changed files
📝
packages/vinext/src/entries/app-rsc-entry.ts(+13 -2)📝
packages/vinext/src/server/app-browser-entry.ts(+151 -23)📝
packages/vinext/src/server/app-browser-state.ts(+8 -0)📝
packages/vinext/src/server/app-elements.ts(+48 -0)📝
packages/vinext/src/server/app-page-boundary-render.ts(+9 -2)📝
packages/vinext/src/server/app-page-route-wiring.tsx(+8 -2)📝
packages/vinext/src/shims/link.tsx(+14 -6)📝
packages/vinext/src/shims/navigation.ts(+54 -16)📝
packages/vinext/src/shims/next-shims.d.ts(+5 -1)📝
tests/__snapshots__/entry-templates.test.ts.snap(+72 -12)📝
tests/app-browser-entry.test.ts(+36 -8)📝
tests/app-elements.test.ts(+44 -0)📝
tests/app-router.test.ts(+11 -1)📝
tests/e2e/app-router/advanced.spec.ts(+87 -19)📝
tests/e2e/app-router/layout-persistence.spec.ts(+3 -20)📝
tests/fixtures/app-basic/app/feed/@modal/(...)photos/[id]/page.tsx(+5 -0)📝
tests/fixtures/app-basic/app/feed/page.tsx(+15 -3)➕
tests/fixtures/app-basic/app/gallery/page.tsx(+16 -0)📝
tests/prefetch-cache.test.ts(+25 -2)📄 Description
Summary
Part of #726 (PR 4). This adds the interception-context identity that PR 2c intentionally deferred. Intercepted App Router navigations now carry their source route through the payload IDs, prefetch cache, visited-response cache, and history state, so
/feed -> /photos/42modal navigations stop aliasing direct/photos/42page loads.The practical effect is that intercepted and direct renders of the same visible pathname no longer stomp each other. Repeated feed/gallery modal navigations reuse the right cached payload, back/forward restores the right source context, and the ordinary visited-response cache still works for non-intercepted navigations.
What changed
__interceptionContextwhen an intercepted render is active, and route/page IDs are encoded with that context instead of keying only by pathnameapp-browser-entryandapp-browser-statenow carry committed interception context alongsideelements,routeId, androotLayoutTreePath, and write it into history state so traversal can recover the original source route/photos/42.rscfrom/feedand/gallerydo not alias each other. Direct-route payloads still omit interception metadata, so visited-response storage preserves the request-side cache partition when the payload does not provide onenext/linkprefetch and App Router navigations sendX-Vinext-Interception-Contextwhen the current render is inside an intercepted flow, and the server reads that header when building intercepted payloadsgallerysource route plus targeted integration/E2E coverage for direct-vs-intercepted cache separation, repeated intercepted navigations, refresh behavior, and interception-aware prefetch entriesWhat this does NOT do
Server action / refresh parity for intercepted routes is still deferred. This PR intentionally leaves action re-renders on the direct-route path and keeps the scope to payload encoding + browser-side cache/history identity.
Test plan
vp test run tests/app-elements.test.ts tests/app-browser-entry.test.ts tests/prefetch-cache.test.tsvp test run tests/app-router.test.ts -t "renders intercepted photo modal on RSC navigation from feed"vp run test:e2e -- tests/e2e/app-router/advanced.spec.ts --project app-routergit commitpre-commit hook (vp check --fix)🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.