fix(nuxt): use more performant router catchall pattern (#31450)

This commit is contained in:
Daniel Roe 2025-03-19 15:05:03 +00:00 committed by GitHub
parent e315a8465f
commit 726c029b33
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 42 additions and 4 deletions

2
.gitignore vendored
View File

@ -80,3 +80,5 @@ eslint-typegen.d.ts
.eslintcache
test-results/
playwright-report
temp

View File

@ -137,7 +137,8 @@ export function generateRoutesFromFiles (files: ScannedFile[], options: Generate
route.name += (route.name && '/') + segmentName
// ex: parent.vue + parent/child.vue
const path = withLeadingSlash(joinURL(route.path, getRoutePath(tokens).replace(INDEX_PAGE_RE, '/')))
const routePath = getRoutePath(tokens, segments[i + 1] !== undefined)
const path = withLeadingSlash(joinURL(route.path, routePath.replace(INDEX_PAGE_RE, '/')))
const child = parent.find(parentRoute => parentRoute.name === route.name && parentRoute.path === path)
if (child && child.children) {
@ -146,7 +147,7 @@ export function generateRoutesFromFiles (files: ScannedFile[], options: Generate
} else if (segmentName === 'index' && !route.path) {
route.path += '/'
} else if (segmentName !== 'index') {
route.path += getRoutePath(tokens)
route.path += routePath
}
}
@ -319,7 +320,7 @@ export function getRouteMeta (contents: string, absolutePath: string, extraExtra
}
const COLON_RE = /:/g
function getRoutePath (tokens: SegmentToken[]): string {
function getRoutePath (tokens: SegmentToken[], hasSucceedingSegment = false): string {
return tokens.reduce((path, token) => {
return (
path +
@ -328,7 +329,7 @@ function getRoutePath (tokens: SegmentToken[]): string {
: token.type === SegmentTokenType.dynamic
? `:${token.value}()`
: token.type === SegmentTokenType.catchall
? `:${token.value}(.*)*`
? hasSucceedingSegment ? `:${token.value}([^/]*)*` : `:${token.value}(.*)*`
: token.type === SegmentTokenType.group
? ''
: encodePath(token.value).replace(COLON_RE, '\\:'))

View File

@ -560,4 +560,15 @@
"redirect": "mockMeta?.redirect",
},
],
"should use more performant regexp when catchall is used in middle of path": [
{
"alias": "mockMeta?.alias || []",
"component": "() => import("pages/[...id]/suffix.vue")",
"meta": "mockMeta || {}",
"name": "mockMeta?.name ?? "id-suffix"",
"path": "mockMeta?.path ?? "/:id([^/]*)*/suffix"",
"props": "mockMeta?.props ?? false",
"redirect": "mockMeta?.redirect",
},
],
}

View File

@ -351,4 +351,11 @@
"redirect": "mockMeta?.redirect",
},
],
"should use more performant regexp when catchall is used in middle of path": [
{
"component": "() => import("pages/[...id]/suffix.vue")",
"name": ""id-suffix"",
"path": ""/:id([^/]*)*/suffix"",
},
],
}

View File

@ -574,6 +574,23 @@ describe('pages:generateRoutesFromFiles', () => {
},
],
},
{
description: 'should use more performant regexp when catchall is used in middle of path',
files: [
{
path: `${pagesDir}/[...id]/suffix.vue`,
},
],
output: [
{
name: 'id-suffix',
meta: undefined,
path: '/:id([^/]*)*/suffix',
file: `${pagesDir}/[...id]/suffix.vue`,
children: [],
},
],
},
{
description: 'should merge route.meta with meta from file',
files: [