Skip to content

Commit 6cc6f7a

Browse files
authored
fix: improve matching perf (#15423)
Assisted-By: devx/597728f0-1b3f-4153-b929-18dbff6cd683
1 parent 69a653e commit 6cc6f7a

2 files changed

Lines changed: 14 additions & 6 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve route matching performance for long paths

packages/react-router/lib/router/utils.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,17 +1584,18 @@ function matchPathImpl<Path extends string>(
15841584
if (!match) return null;
15851585

15861586
let matchedPathname = match[0];
1587-
let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
1587+
let pathnameBase = removeTrailingSlash(matchedPathname, 1);
15881588
let captureGroups = match.slice(1);
15891589
let params: Params = compiledParams.reduce<Mutable<Params>>(
15901590
(memo, { paramName, isOptional }, index) => {
15911591
// We need to compute the pathnameBase here using the raw splat value
15921592
// instead of using params["*"] later because it will be decoded then
15931593
if (paramName === "*") {
15941594
let splatValue = captureGroups[index] || "";
1595-
pathnameBase = matchedPathname
1596-
.slice(0, matchedPathname.length - splatValue.length)
1597-
.replace(/(.)\/+$/, "$1");
1595+
pathnameBase = removeTrailingSlash(
1596+
matchedPathname.slice(0, matchedPathname.length - splatValue.length),
1597+
1,
1598+
);
15981599
}
15991600

16001601
const value = captureGroups[index];
@@ -1944,8 +1945,14 @@ export const removeDoubleSlashes = (path: string): string =>
19441945
export const joinPaths = (paths: string[]): string =>
19451946
removeDoubleSlashes(paths.join("/"));
19461947

1947-
export const removeTrailingSlash = (path: string): string =>
1948-
path.replace(/\/+$/, "");
1948+
// Scan from the end to avoid repeated RegExp work on long paths.
1949+
export function removeTrailingSlash(path: string, minLength = 0): string {
1950+
let end = path.length;
1951+
while (end > minLength && path.charCodeAt(end - 1) === 47) {
1952+
end--;
1953+
}
1954+
return end === path.length ? path : path.slice(0, end);
1955+
}
19491956

19501957
export const normalizePathname = (pathname: string): string =>
19511958
removeTrailingSlash(pathname).replace(/^\/*/, "/");

0 commit comments

Comments
 (0)