mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
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#773
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/690
Author: @Divkix
Created: 3/26/2026
Status: ✅ Merged
Merged: 4/1/2026
Merged by: @james-elicx
Base:
main← Head:fix/firefox-navigation-hang📝 Commits (10+)
030d111fix: cross-route client navigation hangs in Firefox (#652)bdb689dfix: detect React Flight Thenables in updateBrowserTree and apply params eagerlyc19abc7fix: await createFromFetch before passing RSC payload to treee6978c0fix: preserve app router params across cached navigationf062859fix: address review feedback on navigation caching and history management0d5b843merge: resolve conflict for PR 690 Firefox navigation fix0f4f72bfix(navigation): address PR review feedback for Firefox navigation fixffbb964fix: prevent stale navigation bailout from leaking staged paramsab477b7merge: resolve conflicts with origin/main for instrumentation-client support939f0dbfix: remove duplicate onRouterTransitionStart call and fix formatting📊 Changes
18 files changed (+1733 additions, -333 deletions)
View changed files
📝
packages/vinext/src/global.d.ts(+12 -4)📝
packages/vinext/src/server/app-browser-entry.ts(+578 -50)📝
packages/vinext/src/shims/form.tsx(+7 -8)📝
packages/vinext/src/shims/link.tsx(+19 -100)📝
packages/vinext/src/shims/navigation.ts(+580 -153)➕
tests/e2e/app-router/navigation-regressions.spec.ts(+239 -0)➕
tests/fixtures/app-basic/app/nav-flash/link-sync/FilterLinks.tsx(+29 -0)➕
tests/fixtures/app-basic/app/nav-flash/link-sync/page.tsx(+37 -0)➕
tests/fixtures/app-basic/app/nav-flash/list/page.tsx(+26 -0)➕
tests/fixtures/app-basic/app/nav-flash/param-sync/[filter]/FilterControls.tsx(+22 -0)➕
tests/fixtures/app-basic/app/nav-flash/param-sync/[filter]/page.tsx(+20 -0)➕
tests/fixtures/app-basic/app/nav-flash/provider/[id]/page.tsx(+19 -0)➕
tests/fixtures/app-basic/app/nav-flash/query-sync/FilterControls.tsx(+26 -0)➕
tests/fixtures/app-basic/app/nav-flash/query-sync/page.tsx(+27 -0)➕
tests/fixtures/app-basic/app/nav-flash/slow-route/[value]/page.tsx(+28 -0)📝
tests/fixtures/app-basic/app/page.tsx(+6 -0)📝
tests/form.test.ts(+27 -17)📝
tests/prefetch-cache.test.ts(+31 -1)📄 Description
Summary
Fixes #652 —
startTransitionnever commits in Firefox when the entire RSC component tree is replaced during cross-route navigation. The old page stays visible indefinitely in production builds on workerd.Root cause: vinext replaces the full RSC tree on every cross-route navigation inside
startTransition. The React transition scheduler cannot finalize this in Firefox. The previousflushSyncapproach also caused the Suspense double-flash from #639.Fix: Two-phase navigation commit with same-route detection:
startTransitionfor smooth incremental updatesuseLayoutEffectso hooks see the pending URL during transitionsKey changes
navigation.ts:ClientNavigationStateonSymbol.forglobal (survives multiple module instances), render snapshot context for hook consistency during transitions, RSC response snapshot/restore for visited cache, unifiednavigateClientSide()entry point, history suppression helpersapp-browser-entry.ts:BrowserRootcomponent withuseState-managed tree,NavigationCommitSignalthat defers URL commit touseLayoutEffect, visited response cache with LRU eviction (50 entries, 5min TTL — LRU via delete+re-insert promotion on hit, evict oldest-inserted when over capacity), navigation ID counter for stale navigation bailout, manual scroll restorationlink.tsx: removed duplicatedisHashOnlyChange/scrollToHash, delegates tonavigateClientSideform.tsx: App Router GET forms delegate tonavigateClientSideglobal.d.ts: extended__VINEXT_RSC_NAVIGATE__signature withnavigationKindandhistoryUpdateModeEdge cases handled
location.assign)Symbol.forglobal state)Test plan
vp checkpasses (only pre-existing benchmark errors remain)tests/shims.test.ts— 742 tests passtests/form.test.ts— updated assertions for new navigate signature, all passtests/prefetch-cache.test.ts— compatible with newPrefetchCacheEntrytype, all passtests/link.test.ts— all passtests/routing.test.ts— all passtests/app-router.test.ts— all passtests/entry-templates.test.ts— all passtests/e2e/app-router/navigation-regressions.spec.tscovering:usePathname/useSearchParams/useParamshook sync🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.