Skip to content

Commit dbc9cfe

Browse files
authored
refactor(router-core): cache matched route branch alongside the rest of the route match (#5882)
1 parent 40b7576 commit dbc9cfe

File tree

2 files changed

+33
-23
lines changed

2 files changed

+33
-23
lines changed

packages/router-core/src/new-process-route-tree.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ export type ProcessedTree<
537537
/** @deprecated keep until v2 so that `router.matchRoute` can keep not caring about the actual route tree */
538538
singleCache: LRUCache<string, AnySegmentNode<TSingle>>
539539
/** a cache of route matches from the `segmentTree` */
540-
matchCache: LRUCache<string, ReturnType<typeof findMatch<TTree>>>
540+
matchCache: LRUCache<string, RouteMatch<TTree> | null>
541541
/** a cache of route matches from the `masksTree` */
542542
flatCache: LRUCache<string, ReturnType<typeof findMatch<TFlat>>> | null
543543
}
@@ -603,6 +603,12 @@ export function findSingleMatch(
603603
return findMatch(path, tree, fuzzy)
604604
}
605605

606+
type RouteMatch<T extends Extract<RouteLike, { fullPath: string }>> = {
607+
route: T
608+
params: Record<string, string>
609+
branch: ReadonlyArray<T>
610+
}
611+
606612
export function findRouteMatch<
607613
T extends Extract<RouteLike, { fullPath: string }>,
608614
>(
@@ -612,12 +618,17 @@ export function findRouteMatch<
612618
processedTree: ProcessedTree<T, any, any>,
613619
/** If `true`, allows fuzzy matching (partial matches), i.e. which node in the tree would have been an exact match if the `path` had been shorter? */
614620
fuzzy = false,
615-
) {
616-
const key = fuzzy ? `fuzzy\0${path}` : path
621+
): RouteMatch<T> | null {
622+
const key = fuzzy ? path : `nofuzz\0${path}` // the main use for `findRouteMatch` is fuzzy:true, so we optimize for that case
617623
const cached = processedTree.matchCache.get(key)
618-
if (cached) return cached
624+
if (cached !== undefined) return cached
619625
path ||= '/'
620-
const result = findMatch(path, processedTree.segmentTree, fuzzy)
626+
const result = findMatch(
627+
path,
628+
processedTree.segmentTree,
629+
fuzzy,
630+
) as RouteMatch<T> | null
631+
if (result) result.branch = buildRouteBranch(result.route)
621632
processedTree.matchCache.set(key, result)
622633
return result
623634
}
@@ -676,10 +687,7 @@ export function processRouteTree<
676687
const processedTree: ProcessedTree<TRouteLike, any, any> = {
677688
segmentTree,
678689
singleCache: createLRUCache<string, AnySegmentNode<any>>(1000),
679-
matchCache: createLRUCache<
680-
string,
681-
ReturnType<typeof findMatch<TRouteLike>>
682-
>(1000),
690+
matchCache: createLRUCache<string, RouteMatch<TRouteLike> | null>(1000),
683691
flatCache: null,
684692
masksTree: null,
685693
}
@@ -780,6 +788,16 @@ function extractParams<T extends RouteLike>(
780788
return params
781789
}
782790

791+
function buildRouteBranch<T extends RouteLike>(route: T) {
792+
const list = [route]
793+
while (route.parentRoute) {
794+
route = route.parentRoute as T
795+
list.push(route)
796+
}
797+
list.reverse()
798+
return list
799+
}
800+
783801
function buildBranch<T extends RouteLike>(node: AnySegmentNode<T>) {
784802
const list: Array<AnySegmentNode<T>> = Array(node.depth + 1)
785803
do {

packages/router-core/src/router.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ export type ParseLocationFn<TRouteTree extends AnyRoute> = (
697697
) => ParsedLocation<FullSearchSchema<TRouteTree>>
698698

699699
export type GetMatchRoutesFn = (pathname: string) => {
700-
matchedRoutes: Array<AnyRoute>
700+
matchedRoutes: ReadonlyArray<AnyRoute>
701701
routeParams: Record<string, string>
702702
foundRoute: AnyRoute | undefined
703703
}
@@ -1248,9 +1248,9 @@ export class RouterCore<
12481248
next: ParsedLocation,
12491249
opts?: MatchRoutesOpts,
12501250
): Array<AnyRouteMatch> {
1251-
const { foundRoute, matchedRoutes, routeParams } = this.getMatchedRoutes(
1252-
next.pathname,
1253-
)
1251+
const matchedRoutesResult = this.getMatchedRoutes(next.pathname)
1252+
const { foundRoute, routeParams } = matchedRoutesResult
1253+
let { matchedRoutes } = matchedRoutesResult
12541254
let isGlobalNotFound = false
12551255

12561256
// Check to see if the route needs a 404 entry
@@ -1263,7 +1263,7 @@ export class RouterCore<
12631263
) {
12641264
// If the user has defined an (old) 404 route, use it
12651265
if (this.options.notFoundRoute) {
1266-
matchedRoutes.push(this.options.notFoundRoute)
1266+
matchedRoutes = [...matchedRoutes, this.options.notFoundRoute]
12671267
} else {
12681268
// If there is no routes found during path matching
12691269
isGlobalNotFound = true
@@ -2642,15 +2642,7 @@ export function getMatchedRoutes<TRouteLike extends RouteLike>({
26422642
Object.assign(routeParams, match.params) // Copy params, because they're cached
26432643
}
26442644

2645-
let routeCursor: TRouteLike = foundRoute || routesById[rootRouteId]!
2646-
2647-
const matchedRoutes: Array<TRouteLike> = [routeCursor]
2648-
2649-
while (routeCursor.parentRoute) {
2650-
routeCursor = routeCursor.parentRoute as TRouteLike
2651-
matchedRoutes.push(routeCursor)
2652-
}
2653-
matchedRoutes.reverse()
2645+
const matchedRoutes = match?.branch || [routesById[rootRouteId]!]
26542646

26552647
return { matchedRoutes, routeParams, foundRoute }
26562648
}

0 commit comments

Comments
 (0)