-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
refactor(router-core): processRouteTree sorting uses constants for all score modifiers #5131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor(router-core): processRouteTree sorting uses constants for all score modifiers #5131
Conversation
…l score modifiers
WalkthroughRefactors route scoring in process-route-tree to use new constants and a full lookahead for dynamic parameters, adding a bonus when any subsequent static segment exists. Standardizes PATHNAME scoring, handles wildcard via general branch, and removes fallback scoring quirks without changing public APIs. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor App as App
participant Router as Router
participant Processor as RouteProcessor
participant Scorer as SegmentScorer
App->>Router: register routes / resolve request
Router->>Processor: processRouteTree(segments)
loop for each segment
Processor->>Scorer: score(segment)
alt PATHNAME
Scorer-->>Processor: STATIC_SEGMENT_SCORE or SLASH_SCORE
else Dynamic Param
Scorer->>Scorer: scan subsequent segments
alt any subsequent static pathname exists
Note right of Scorer: Apply STATIC_AFTER_DYNAMIC_BONUS_SCORE
Scorer-->>Processor: baseScore + bonus via handleParam
else none found
Scorer-->>Processor: baseScore via handleParam
end
else Wildcard/Other
Scorer-->>Processor: baseScore via general branch
end
end
Processor-->>Router: ranked routes
Router-->>App: selected route
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Pre-merge checks (2 passed, 1 warning)❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Poem
✨ Finishing touches
🧪 Generate unit tests
Comment |
|
View your CI Pipeline Execution ↗ for commit fc8b367
☁️ Nx Cloud last updated this comment at |
More templates
@tanstack/arktype-adapter
@tanstack/directive-functions-plugin
@tanstack/eslint-plugin-router
@tanstack/history
@tanstack/react-router
@tanstack/react-router-devtools
@tanstack/react-router-ssr-query
@tanstack/react-start
@tanstack/react-start-client
@tanstack/react-start-plugin
@tanstack/react-start-server
@tanstack/router-cli
@tanstack/router-core
@tanstack/router-devtools
@tanstack/router-devtools-core
@tanstack/router-generator
@tanstack/router-plugin
@tanstack/router-ssr-query-core
@tanstack/router-utils
@tanstack/router-vite-plugin
@tanstack/server-functions-plugin
@tanstack/solid-router
@tanstack/solid-router-devtools
@tanstack/solid-start
@tanstack/solid-start-client
@tanstack/solid-start-plugin
@tanstack/solid-start-server
@tanstack/start-client-core
@tanstack/start-plugin-core
@tanstack/start-server-core
@tanstack/start-server-functions-client
@tanstack/start-server-functions-fetcher
@tanstack/start-server-functions-server
@tanstack/start-storage-context
@tanstack/valibot-adapter
@tanstack/virtual-file-routes
@tanstack/zod-adapter
commit: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
packages/router-core/src/process-route-tree.ts (4)
13-18: Good extraction of scoring knobs; add brief rationale docstrings.Constants make tuning explicit. Add 1–2 line comments on why 0.75/1/0.2 were chosen to help future maintainers adjust safely.
85-91: Unify PATHNAME and slash handling to one branch.Slightly simplifies control flow and ensures slash is only treated when type is PATHNAME.
- if (segment.value === '/') { - return SLASH_SCORE - } - - if (segment.type === SEGMENT_TYPE_PATHNAME) { - return STATIC_SEGMENT_SCORE - } + if (segment.type === SEGMENT_TYPE_PATHNAME) { + return segment.value === '/' ? SLASH_SCORE : STATIC_SEGMENT_SCORE + }
99-101: Prefer explicit wildcard handling over a catch-all else.Future segment types will be accidentally scored as wildcard. Handle the wildcard explicitly and make unknown types obvious.
- } else { - baseScore = WILDCARD_PARAM_BASE_SCORE - } + } else if (segment.type === SEGMENT_TYPE_WILDCARD) { + baseScore = WILDCARD_PARAM_BASE_SCORE + } else { + baseScore = 0 // unknown type; intentionally lowest score + }Add the missing import:
// top of file import { SEGMENT_TYPE_WILDCARD } from './path'
103-117: Guard the dynamic lookahead bonus to params only; avoid awarding wildcard and rename inner loop index.Comment says the boost is for required/optional params, but current code applies to any non-PATHNAME (including wildcard). Guard it and avoid shadowing outer i.
- // if there is any static segment (that is not an index) after a required / optional param, - // we will boost this param so it ranks higher than a required/optional param without a static segment after it - // JUST FOR SORTING, NOT FOR MATCHING - for (let i = index + 1; i < parsed.length; i++) { - const nextSegment = parsed[i]! - if ( - nextSegment.type === SEGMENT_TYPE_PATHNAME && - nextSegment.value !== '/' - ) { - hasStaticAfter = true - return handleParam( - segment, - baseScore + STATIC_AFTER_DYNAMIC_BONUS_SCORE, - ) - } - } - - return handleParam(segment, baseScore) + // Only boost required/optional params when a later static segment exists (not index '/') + if ( + segment.type === SEGMENT_TYPE_PARAM || + segment.type === SEGMENT_TYPE_OPTIONAL_PARAM + ) { + for (let j = index + 1; j < parsed.length; j++) { + const nextSegment = parsed[j]! + if ( + nextSegment.type === SEGMENT_TYPE_PATHNAME && + nextSegment.value !== '/' + ) { + hasStaticAfter = true + return handleParam( + segment, + baseScore + STATIC_AFTER_DYNAMIC_BONUS_SCORE, + ) + } + } + } + return handleParam(segment, baseScore)Optional: precompute a suffix array like hasStaticAfterFrom[i] in O(n) to avoid O(n^2) scans per route if paths get long.
Also applies to: 120-120
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/router-core/src/process-route-tree.ts(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/router-core/src/process-route-tree.ts (1)
packages/router-core/src/path.ts (1)
SEGMENT_TYPE_PATHNAME(6-6)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Preview
- GitHub Check: Test
…l score modifiers (TanStack#5131) Just to make it easier to tweak the values and understand the scales / functions, we extract all score modifiers to constants w/ descriptive names. This PR is a no-op, no logic was modified. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - Bug Fixes - Improved route matching accuracy by prioritizing routes with static segments that appear after dynamic parameters. - More predictable matching in complex paths; reduces unexpected selections. - Wildcard routes handled more consistently. - Refactor - Updated internal route scoring to consider deeper static segments without changing the public API. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Just to make it easier to tweak the values and understand the scales / functions, we extract all score modifiers to constants w/ descriptive names.
This PR is a no-op, no logic was modified.
Summary by CodeRabbit
Bug Fixes
Refactor