mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
[GH-ISSUE #980] perf: shared route scan cache to eliminate 3-5x duplicate directory scans #212
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#212
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?
Originally created by @Divkix on GitHub (Apr 30, 2026).
Original GitHub issue: https://github.com/cloudflare/vinext/issues/980
Problem
The app/pages directories are scanned from scratch at 5+ different phases, with no shared cache:
index.ts:1656appRouter()**/page+**/routeindex.ts:1692appRouter()againindex.ts:2666apiRouter()index.ts:2696pagesRouter()build/run-prerender.ts:204,236-237build/report.ts:926-937,build/nitro-route-rules.ts:40-46Each
appRouter()call runsscanWithExtensions("**/page", ...)+scanWithExtensions("**/route", ...)sequentially. These are full directory glob operations.Current caching
app-router.ts:144-152: Module-level cache (cachedRoutes,cachedAppDir,cachedPageExtensionsKey). Invalidated entirely byinvalidateAppRouteCache()on any file change (all-or-nothing).pages-router.ts:25-37:Map<string, ...>keyed bypages:${dir}:${extensions}. Also all-or-nothing invalidation.Both caches exist but are isolated — they don't communicate between the different call sites. The RSC entry load at
index.ts:1656scans, then the root-params load atindex.ts:1692scans the same directory again 30 lines later.Why it matters
invalidateAppRouteCache()atindex.ts:2052-2071)pagesRouter()called every request atindex.ts:2696Proposed fix
Create a single shared route cache on the plugin instance closure in
index.tsthat all consumers reference:root,appDir,pagesDir, etc. atindex.ts:521-560)appRouter(),pagesRouter(),apiRouter()instead of having them scanindex.ts:2666,index.ts:2696): use cached routes, don't rescanFor incremental invalidation: instead of
invalidateAppRouteCache()clearing everything, use the file watcher'sadd/unlinkevents to add/remove individual routes. The trie (route-trie.ts) can be updated incrementally (insert/remove operations already exist).Estimated files touched: 5-7
index.tsrouting/app-router.tsrouting/pages-router.tsentries/pages-server-entry.tsentries/pages-client-entry.tsbuild/run-prerender.tsbuild/report.ts,build/nitro-route-rules.tsDifficulty: Medium
Plumbing work. Caching infrastructure exists, just needs to be unified and made incremental.
Expected improvement
@Divkix commented on GitHub (Apr 30, 2026):
Closing: existing module-level caches already prevent the described redundant scans.
app-router.ts:174: cache hit on second call within same invalidation cyclepages-router.ts:58-59: cached promise returned on all per-request callsapp-router.ts:174+pages-router.ts:204-206: dev middleware never rescansAll caches invalidate correctly on file watcher add/unlink events. No redundant glob operations observed.