Skip to content

refactor(router-core): skip full matchRoutesInternal for Link's buildLocation, use simple getMatchedRoutes - #6445

Merged
Sheraff merged 7 commits into
mainfrom
refactor-router-core-skip-full-route-match-build-for-location-only-link
Jan 22, 2026
Merged

refactor(router-core): skip full matchRoutesInternal for Link's buildLocation, use simple getMatchedRoutes#6445
Sheraff merged 7 commits into
mainfrom
refactor-router-core-skip-full-route-match-build-for-location-only-link

Conversation

@Sheraff

@SheraffSheraff commented Jan 21, 2026

Copy link
Copy Markdown
Collaborator

SSR benchmarks for 100 parallel connections, fetching pages w/ 100 links

Before:

21k requests in 30.02s, 283 MB read
=== SSR Benchmark Results ===
Total requests: 20949
Requests/sec: 698.3
Latency (avg): 142.4ms
Latency (p99): 231ms
Throughput: 8.99 MB/s

After

24k requests in 30.02s, 328 MB read
=== SSR Benchmark Results ===
Total requests: 24322
Requests/sec: 810.74
Latency (avg): 122.6ms
Latency (p99): 185ms
Throughput: 10.44 MB/s

Summary by CodeRabbit

  • Refactor
    • Reduced routing overhead with a lightweight matching path and centralized global 404 resolution, preserving URL params and search state for more consistent, responsive navigation.
  • Tests
    • Adjusted test expectations across frameworks to reflect fewer or no mock invocations during several navigation and rendering scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitaiBot commented Jan 21, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Replaces full-match construction in buildLocation with lightweight getMatchedRoutes to obtain destRoutes/rawParams, centralizes global-not-found determination via a new findGlobalNotFoundRouteId, threads globalNotFoundRouteId into buildMatchSnapshotFromRoutes, and updates framework useParams test expectations.

Changes

Cohort / File(s)Summary
Router core
packages/router-core/src/router.ts
Replace heavy matchRoutesInternal usage with getMatchedRoutes returning destRoutes and rawParams; add findGlobalNotFoundRouteId(notFoundMode, routes); compute and pass globalNotFoundRouteId into buildMatchSnapshotFromRoutes; extend its signature; change applySearchMiddleware param to ReadonlyArray<AnyRoute>; preserve destParams in params flow.
Framework tests (useParams)
packages/react-router/tests/useParams.test.tsx, packages/solid-router/tests/useParams.test.tsx, packages/vue-router/tests/useParams.test.tsx
Update mocked function invocation assertions to expect fewer or no calls (use not.toHaveBeenCalled() or reduced counts) to reflect the revised matching/resolution behavior during navigation and rendering.

Sequence Diagram(s)

sequenceDiagram
participant Client as Client
participant Router as Router.buildLocation
participant Matcher as getMatchedRoutes
participant Finder as findGlobalNotFoundRouteId
participant Snapshot as buildMatchSnapshotFromRoutes
participant Location as LocationBuilder
Client->>Router: navigate(request)
Router->>Matcher: getMatchedRoutes(destPath)
Note right of Matcher: returns destRoutes + rawParams
Router->>Finder: findGlobalNotFoundRouteId(notFoundMode, destRoutes)
Finder-->>Router: globalNotFoundRouteId
Router->>Snapshot: buildMatchSnapshotFromRoutes(routes, params, searchStr, globalNotFoundRouteId)
Snapshot-->>Router: match snapshot
Router->>Location: assemble final Location with snapshot
Location-->>Client: navigation completed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

Suggested reviewers

  • schiller-manuel
  • nlynzaad

Poem

🐇
I hopped through maps and paths anew,
Swapped heavy matches for a lighter view.
I chased the lost route, gave it a sign,
Threaded snapshots neat — the rails align.
Thump-thump, the router hums — hooray, it's fine.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title directly and specifically describes the main change: refactoring router-core to use the lightweight getMatchedRoutes instead of the full matchRoutesInternal path for Link's buildLocation function.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud

nx-cloudBot commented Jan 21, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 99c67fe

CommandStatusDurationResult
nx affected --targets=test:eslint,test:unit,tes...✅ Succeeded12m 37sView ↗
nx run-many --target=build --exclude=examples/*...✅ Succeeded1m 41sView ↗

☁️ Nx Cloud last updated this comment at 2026-01-22 21:18:06 UTC

@pkg-pr-new

pkg-pr-newBot commented Jan 21, 2026

Copy link
Copy Markdown
More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@6445

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/eslint-plugin-router@6445

@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@6445

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/nitro-v2-vite-plugin@6445

@tanstack/react-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router@6445

@tanstack/react-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@6445

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-ssr-query@6445

@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@6445

@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@6445

@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@6445

@tanstack/router-cli

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-cli@6445

@tanstack/router-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-core@6445

@tanstack/router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools@6445

@tanstack/router-devtools-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools-core@6445

@tanstack/router-generator

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-generator@6445

@tanstack/router-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@6445

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-ssr-query-core@6445

@tanstack/router-utils

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-utils@6445

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-vite-plugin@6445

@tanstack/solid-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router@6445

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-devtools@6445

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-ssr-query@6445

@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@6445

@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@6445

@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@6445

@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@6445

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-fn-stubs@6445

@tanstack/start-plugin-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@6445

@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@6445

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-static-server-functions@6445

@tanstack/start-storage-context

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@6445

@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@6445

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@6445

@tanstack/vue-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router@6445

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-devtools@6445

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-ssr-query@6445

@tanstack/vue-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start@6445

@tanstack/vue-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-client@6445

@tanstack/vue-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-server@6445

@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@6445

commit: d0092a8

Comment threadpackages/router-core/src/router.ts
Comment threadpackages/router-core/src/router.ts

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/router-core/src/router.ts`:
- Around line 1765-1788: In buildLocation the snapshot uses getMatchedRoutes
(destMatchResult -> destRoutes) which doesn't append a notFound route, so
snapshots can omit the 404 route; update buildLocation to mirror
matchRoutesInternal by appending this.options.notFoundRoute to destRoutes when
present and only compute globalNotFoundRouteId via
findGlobalNotFoundRouteId(this.options.notFoundMode, destRoutes) when there is
no custom this.options.notFoundRoute; ensure references to destRoutes,
globalNotFoundRouteId, this.options.notFoundRoute, getMatchedRoutes, and
findGlobalNotFoundRouteId are adjusted so the snapshot includes the notFound
route and still falls back to globalNotFoundRouteId when no custom notFoundRoute
exists.

Comment threadpackages/router-core/src/router.ts
@Sheraff

Copy link
Copy Markdown
CollaboratorAuthor

Comparing the new code (16:07:01) vs main branch (16:13:51):

Overview Comparison

MetricNew CodeMain BranchVerdict
Duration16.3s15.9sMain slightly faster
Samples274240-
Critical Path 141.1%45.4%✅ New wins (-9.5%)
Application code-36.7%-

Hotspot Comparison

FunctionNew CodeMain BranchVerdict
(anonymous) link.js:3214.6%5.7%✅ New wins (-19%)
Garbage Collection5.1%5.2%≈ Same
(anonymous) router.js1.6% (L#1124)4.9% (L#1130)✅ New wins (-67%)
useLinkProps3.2%2.4%❌ New regressed (+33%)
buildWithMatches-2.7%✅ Not in new top 10
build-2.7%✅ Not in new top 10
matchRoutesInternal-2.7%✅ Not in new top 10
getEnumerableOwnKeys1.6%2.4%✅ New wins (-33%)
parseSegment-1.9%✅ Not in new top 10

What Changed

Dropped from main's top 10 in new code:

  • buildWithMatches (was 2.7%)
  • build (was 2.7%)
  • matchRoutesInternal (was 2.7%)
  • parseSegment (was 1.9%)

New in new code's top 10:

  • writev at 1.6%
  • (anonymous:L#1444:C#5) at 1.6%
  • nextTick at 1.4%
  • emit at 1.4%

Line Number Shifts

  • router.js: 1130 → 1124 (anonymous function)
  • Route tree processing code location changed

Summary

AspectWinnerDelta
Critical path✅ New code-9.5% (45.4% → 41.1%)
link.js:321✅ New code-19% (5.7% → 4.6%)
router.js anonymous✅ New code-67% (4.9% → 1.6%)
Route matching✅ New codeAll 3 functions dropped out
getEnumerableOwnKeys✅ New code-33% (2.4% → 1.6%)
useLinkProps❌ Main branch+33% (2.4% → 3.2%)
GC≈ Tie~same (5.2% vs 5.1%)

Bottom line: The new code shows significant improvements across most metrics:

  • Critical path reduced by ~10%
  • Route matching code (buildWithMatches, build, matchRoutesInternal, parseSegment) all dropped out of the top 10
  • The router anonymous function improved by 67%
  • Link anonymous function improved by 19%

The only regression is useLinkProps (+33%), but this is offset by the improvement in the link anonymous function, and both are in the same code path. Overall, new code appears to be a net performance win.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Sheraff