Skip to content

Conversation

@Sheraff
Copy link
Contributor

@Sheraff Sheraff commented Jan 21, 2026

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
Copy link
Contributor

coderabbitai bot commented Jan 21, 2026

📝 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 name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring 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 name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The 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
Copy link

nx-cloud bot commented Jan 21, 2026

View your CI Pipeline Execution ↗ for commit 99c67fe

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 12m 37s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 41s View ↗

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

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 21, 2026

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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.

@Sheraff
Copy link
Contributor Author

Sheraff commented Jan 22, 2026

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

Overview Comparison

Metric New Code Main Branch Verdict
Duration 16.3s 15.9s Main slightly faster
Samples 274 240 -
Critical Path 1 41.1% 45.4% ✅ New wins (-9.5%)
Application code - 36.7% -

Hotspot Comparison

Function New Code Main Branch Verdict
(anonymous) link.js:321 4.6% 5.7% ✅ New wins (-19%)
Garbage Collection 5.1% 5.2% ≈ Same
(anonymous) router.js 1.6% (L#1124) 4.9% (L#1130) ✅ New wins (-67%)
useLinkProps 3.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
getEnumerableOwnKeys 1.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

Aspect Winner Delta
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 code All 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.

@Sheraff Sheraff merged commit 655496f into main Jan 22, 2026
4 of 5 checks passed
@Sheraff Sheraff deleted the refactor-router-core-skip-full-route-match-build-for-location-only-link branch January 22, 2026 22:24
Sign up for free to 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.

2 participants