Skip to content

Conversation

@Sheraff
Copy link
Contributor

@Sheraff Sheraff commented Jan 23, 2026

The buildLocation function needs some information about the from location.

Before this PR, to get this information we would build a full match branch through matchRoutes, but with a _buildLocation: true argument that skipped some things.

This PR proposes that we implement a fully separate function that can skip much more work. We also allow for the case where from is the current location to short-circuit search validation and params validation.

Before
Screenshot 2026-01-23 at 14 40 34

After
Screenshot 2026-01-23 at 15 04 23

Summary by CodeRabbit

  • Breaking Changes

    • Removed the optional build-location flag from route-matching configuration (public interface change).
  • Performance Improvements

    • Added a lightweight route-matching path to speed up path computation and validation.
  • Bug Fixes

    • Consolidated parameter parsing and unified error propagation for more consistent handling during route resolution.

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

@nx-cloud
Copy link

nx-cloud bot commented Jan 23, 2026

View your CI Pipeline Execution ↗ for commit 540f118

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

☁️ Nx Cloud last updated this comment at 2026-01-23 22:50:27 UTC

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 23, 2026

📝 Walkthrough

Walkthrough

Removed the _buildLocation flag from MatchRoutesOpts. Added a private matchRoutesLightweight(location) that returns matchedRoutes, fullPath, search, and params. buildLocation and related from/fromCurrentPath flows now use the lightweight result and a centralized extractStrictParams for parameter parsing and consistent error propagation.

Changes

Cohort / File(s) Change Summary
Router core (matching & buildLocation)
packages/router-core/src/router.ts
Removed _buildLocation?: boolean from MatchRoutesOpts. Added matchRoutesLightweight(location) returning { matchedRoutes, fullPath, search, params }. Switched buildLocation and from/fromCurrentPath validations to use lightweight results. Added extractStrictParams to centralize param parsing/error propagation. Adjusted internal applySearchMiddleware wiring to accept a lighter { search?: unknown } shape. (+117 / -42)

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Router
  participant MatchLight as matchRoutesLightweight
  participant ParamExt as extractStrictParams

  Caller->>Router: buildLocation(currentLocation)
  Router->>MatchLight: matchRoutesLightweight(location)
  MatchLight-->>Router: { matchedRoutes, fullPath, search, params }
  Router->>ParamExt: extractStrictParams(params, routeDefs)
  ParamExt-->>Router: parsedParams or PathParamError
  Router-->>Caller: built Location (using lightweight result + parsedParams)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

performance

Suggested reviewers

  • schiller-manuel
  • nlynzaad

Poem

"I’m a rabbit in the router wood,
I trim the matches where I could,
Lightweight hops and tidy params,
I skip the weight and save your RAMs,
Quick little paws — hop on, all good! 🐇"

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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 accurately describes the main change: refactoring buildLocation for performance by simplifying 'from' location parsing, which matches the core focus of removing _buildLocation flag and introducing lightweight matching.

✏️ 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.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 23, 2026

More templates

@tanstack/arktype-adapter

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

@tanstack/eslint-plugin-router

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

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-fn-stubs

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

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

@tanstack/vue-start-client

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

@tanstack/vue-start-server

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

@tanstack/zod-adapter

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

commit: 540f118

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 1696-1716: The lightweight param-parsing loop in
matchRoutesInternal currently calls route.options.params?.parse (parseParams)
even for routes marked skipRouteOnParseError, which breaks the original
semantics; modify the matchedRoutes loop so that you first check
route.options.skipRouteOnParseError and, if true, skip invoking parseParams
entirely and instead copy pre-parsed values from parsedParams into
accumulatedParams (as the existing else branch does), otherwise proceed to call
parseParams and merge results into accumulatedParams; update logic around
accumulatedParams, parseParams, parsedParams, and
route.options.skipRouteOnParseError to match the behavior used during
buildLocation.
🧹 Nitpick comments (1)
packages/router-core/src/router.ts (1)

1606-1609: Update stale comment on context execution.

The guard now only checks !existingMatch, so the comment about buildLocation no longer reflects the actual condition. Consider updating or removing it to avoid confusion.

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 1680-1684: The loop that calls extractStrictParams over
matchedRoutes lacks error handling and can let parseParams exceptions bubble up
and crash buildLocation; wrap the body that calls extractStrictParams (the loop
iterating matchedRoutes which assigns strictParams and later sets params) in a
try-catch, mirror the pattern used in matchRoutesInternal around
extractStrictParams, catch and rethrow or return a controlled error (including
route identity/context) so buildLocation can handle malformed URL params
gracefully; update the scope where params = strictParams to only run if no
exception was thrown.
♻️ Duplicate comments (1)
packages/router-core/src/router.ts (1)

1652-1667: Consider extracting shared search accumulation logic.

This search validation loop mirrors the pattern in matchRoutesInternal. As noted in past reviews, extracting a shared helper could reduce duplication.

Comment on lines 1652 to 1670
// Accumulate search validation through the route chain
const accumulatedSearch: Record<string, unknown> = applySearchMiddleware({
search: { ...location.search },
dest: location,
destRoutes: matchedRoutes,
_includeValidateSearch: true,
})
// I don't know if we should run the full search middleware chain, or just validateSearch
// let accumulatedSearch = { ...location.search }
// for (const route of matchedRoutes) {
// try {
// Object.assign(
// accumulatedSearch,
// validateSearch(route.options.validateSearch, accumulatedSearch),
// )
// } catch {
// // Ignore errors, we're not actually routing
// }
// }
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@schiller-manuel any idea if we should just run the validateSearch or if we need to run the full applySearchMiddleware (with _includeValidateSearch) when building the from data for buildLocation?

I do know that we need to run one of them, but idk which one.

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 1652-1669: matchRoutesLightweight currently calls
applySearchMiddleware (with _includeValidateSearch: true) against the current
location which runs full custom search middleware on the "from" location and can
double‑apply non‑idempotent logic; instead run only validation like the
commented loop: iterate matchedRoutes and call
validateSearch(route.options.validateSearch, accumulatedSearch) catching errors
and merging results into accumulatedSearch (using Object.assign) so only
validation runs for the current location and buildLocation can still run the
full middleware once for the destination; reference applySearchMiddleware,
matchRoutesLightweight, validateSearch, buildLocation, matchedRoutes and
location.search when making the change.
🧹 Nitpick comments (1)
packages/router-core/src/router.ts (1)

3096-3104: Tighten dest typing to keep TypeScript safety.

dest: { search?: unknown } weakens type guarantees around search (e.g., updater vs object). Consider a small union that preserves the expected shapes while still accepting ParsedLocation.

♻️ Suggested typing refinement
+type SearchDest = {
+  search?: true | Updater<unknown> | Record<string, unknown>
+}
 function applySearchMiddleware({
   search,
   dest,
   destRoutes,
   _includeValidateSearch,
 }: {
   search: any
-  dest: { search?: unknown }
+  dest: SearchDest
   destRoutes: ReadonlyArray<AnyRoute>
   _includeValidateSearch: boolean | undefined
 }) {

@Sheraff Sheraff merged commit f26cf54 into main Jan 23, 2026
6 checks passed
@Sheraff Sheraff deleted the refactor-router-core-build-location-from-parsing-performance branch January 23, 2026 23:28
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