Skip to content

Commit 308d206

Browse files
authored
fix: improve matching perf (#15417)
Assisted-By: devx/597728f0-1b3f-4153-b929-18dbff6cd683
1 parent 36bdbeb commit 308d206

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
@@ -1692,17 +1692,18 @@ function matchPathImpl<Path extends string>(
16921692
if (!match) return null;
16931693

16941694
let matchedPathname = match[0];
1695-
let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
1695+
let pathnameBase = removeTrailingSlash(matchedPathname, 1);
16961696
let captureGroups = match.slice(1);
16971697
let params: Params = compiledParams.reduce<Mutable<Params>>(
16981698
(memo, { paramName, isOptional }, index) => {
16991699
// We need to compute the pathnameBase here using the raw splat value
17001700
// instead of using params["*"] later because it will be decoded then
17011701
if (paramName === "*") {
17021702
let splatValue = captureGroups[index] || "";
1703-
pathnameBase = matchedPathname
1704-
.slice(0, matchedPathname.length - splatValue.length)
1705-
.replace(/(.)\/+$/, "$1");
1703+
pathnameBase = removeTrailingSlash(
1704+
matchedPathname.slice(0, matchedPathname.length - splatValue.length),
1705+
1,
1706+
);
17061707
}
17071708

17081709
const value = captureGroups[index];
@@ -2054,8 +2055,14 @@ export const removeDoubleSlashes = (path: string): string =>
20542055
export const joinPaths = (paths: string[]): string =>
20552056
removeDoubleSlashes(paths.join("/"));
20562057

2057-
export const removeTrailingSlash = (path: string): string =>
2058-
path.replace(/\/+$/, "");
2058+
// Scan from the end to avoid repeated RegExp work on long paths.
2059+
export function removeTrailingSlash(path: string, minLength = 0): string {
2060+
let end = path.length;
2061+
while (end > minLength && path.charCodeAt(end - 1) === 47) {
2062+
end--;
2063+
}
2064+
return end === path.length ? path : path.slice(0, end);
2065+
}
20592066

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

0 commit comments

Comments
 (0)