@@ -2,6 +2,30 @@ import { logger } from '@sentry/core';
2
2
import type { NuxtSSRContext } from 'nuxt/app' ;
3
3
import type { NuxtPage } from 'nuxt/schema' ;
4
4
5
+ export type NuxtPageSubset = { path : NuxtPage [ 'path' ] ; file : NuxtPage [ 'file' ] } ;
6
+
7
+ // buildTimePagesData -> Map<file, path>
8
+ const routeMappingCache = new WeakMap < NuxtPageSubset [ ] , Map < string , string > > ( ) ;
9
+
10
+ /**
11
+ * Creates a mapping from module paths to parametrized routes for faster lookup.
12
+ * The `buildTimePagesData` doesn't change during SSR, as it's generated at build time.
13
+ */
14
+ function createRouteMapping ( buildTimePagesData : NuxtPageSubset [ ] ) : Map < string , string > {
15
+ const mapping = new Map < string , string > ( ) ;
16
+
17
+ for ( const routeData of buildTimePagesData ) {
18
+ if ( routeData . file && routeData . path ) {
19
+ // Handle Unix and Windows paths
20
+ const normalizedFile = routeData . file . replace ( / \\ / g, '/' ) ;
21
+ mapping . set ( normalizedFile , routeData . path ) ;
22
+ }
23
+ }
24
+
25
+ routeMappingCache . set ( buildTimePagesData , mapping ) ;
26
+ return mapping ;
27
+ }
28
+
5
29
/**
6
30
* Extracts route information from the SSR context modules and URL.
7
31
*
@@ -17,12 +41,12 @@ import type { NuxtPage } from 'nuxt/schema';
17
41
*
18
42
* @param buildTimePagesData
19
43
* An array of NuxtPage objects representing the build-time pages data.
20
- * Example: [{ name : 'some- path', path: '/some/path' }, { name : 'user- userId', path: '/user/:userId()' }]
44
+ * Example: [{ file : '/a/file/pages/ some/ path', path: '/some/path' }, { file : '/a/file/pages/ user/[ userId].vue ', path: '/user/:userId()' }]
21
45
*/
22
46
export function extractParametrizedRouteFromContext (
23
47
ssrContextModules ?: NuxtSSRContext [ 'modules' ] ,
24
48
currentUrl ?: NuxtSSRContext [ 'url' ] ,
25
- buildTimePagesData : NuxtPage [ ] = [ ] ,
49
+ buildTimePagesData : NuxtPageSubset [ ] = [ ] ,
26
50
) : null | { parametrizedRoute : string } {
27
51
if ( ! ssrContextModules || ! currentUrl ) {
28
52
logger . warn ( 'SSR context modules or URL is not available.' ) ;
@@ -35,30 +59,24 @@ export function extractParametrizedRouteFromContext(
35
59
36
60
const modulesArray = Array . from ( ssrContextModules ) ;
37
61
38
- // Find the route data that corresponds to a module in ssrContext.modules
39
- const foundRouteData = buildTimePagesData . find ( routeData => {
40
- if ( ! routeData . file ) return false ;
41
-
42
- return modulesArray . some ( module => {
43
- // Extract the folder name and relative path from the page file
44
- // e.g., 'pages/test-param/[param].vue' -> folder: 'pages', path: 'test-param/[param].vue'
45
- const filePathParts = module . split ( '/' ) ;
62
+ const existingRouteMapping = routeMappingCache . get ( buildTimePagesData ) ;
63
+ const routeMapping = existingRouteMapping || createRouteMapping ( buildTimePagesData ) ;
46
64
47
- // Exclude root-level files (e.g., 'app.vue')
48
- if ( filePathParts . length < 2 ) return false ;
65
+ const modulePagePaths = modulesArray . map ( module => {
66
+ const filePathParts = module . split ( '/' ) ;
67
+ if ( filePathParts . length < 2 ) return null ;
49
68
50
- // Normalize path separators to handle both Unix and Windows paths
51
- const normalizedRouteFile = routeData . file ?. replace ( / \\ / g, '/' ) ;
52
-
53
- const pagesFolder = filePathParts [ 0 ] ;
54
- const pageRelativePath = filePathParts . slice ( 1 ) . join ( '/' ) ;
55
-
56
- // Check if any module in ssrContext.modules ends with the same folder/relative path structure
57
- return normalizedRouteFile ?. endsWith ( `/${ pagesFolder } /${ pageRelativePath } ` ) ;
58
- } ) ;
69
+ const pagesFolder = filePathParts [ 0 ] ;
70
+ const pageRelativePath = filePathParts . slice ( 1 ) . join ( '/' ) ;
71
+ return `/${ pagesFolder } /${ pageRelativePath } ` ;
59
72
} ) ;
60
73
61
- const parametrizedRoute = foundRouteData ?. path ?? null ;
74
+ for ( const [ pageFile , route ] of routeMapping ) {
75
+ // Check if any module of the requested page ends with the same folder/relative path structure as the parametrized filePath from build time.
76
+ if ( modulePagePaths . some ( filePath => filePath && pageFile . endsWith ( filePath ) ) ) {
77
+ return { parametrizedRoute : route } ;
78
+ }
79
+ }
62
80
63
- return parametrizedRoute === null ? null : { parametrizedRoute } ;
81
+ return null ;
64
82
}
0 commit comments