@@ -24,17 +24,35 @@ const keepClientSourceMaps = process.env.E2E_KEEP_CLIENT_SOURCEMAPS === 'true';
2424/** `nuxt generate` emits no `.output/server`. Keyed on the command so a missing one under `nuxt build` still fails. */
2525const isStaticBuild = process . env . NUXT_COMMAND === 'generate' ;
2626
27- const CLIENT_OUTPUT = path . join ( '.output' , 'public' ) ;
27+ const nitroPreset = process . env . NITRO_PRESET ?? 'node-server' ;
28+
29+ /** If Nitro moves one of these directories, the debug ID checks below fail. */
30+ const OUTPUT_DIRS : Record < string , { client : string ; server : string } > = {
31+ 'node-server' : { client : path . join ( '.output' , 'public' ) , server : path . join ( '.output' , 'server' ) } ,
32+ netlify : { client : 'dist' , server : path . join ( '.netlify' , 'functions-internal' , 'server' ) } ,
33+ 'cloudflare-pages' : { client : 'dist' , server : path . join ( 'dist' , '_worker.js' ) } ,
34+ } ;
35+
36+ const outputDirs = OUTPUT_DIRS [ nitroPreset ] ;
37+ assert . ok ( outputDirs , `Expected output directories for the Nitro preset ${ nitroPreset } ` ) ;
38+
39+ const CLIENT_OUTPUT = outputDirs . client ;
2840/** Vite's own output directory. Nitro copies it to `CLIENT_OUTPUT`, and Sentry deletes no maps here. */
2941const CLIENT_BUILD_OUTPUT = path . join ( '.nuxt' , 'dist' , 'client' ) ;
30- const SERVER_OUTPUT = path . join ( '.output' , ' server' ) ;
42+ const SERVER_OUTPUT = outputDirs . server ;
3143
3244/** Both markers sit in comments, so bundlers strip them from the code but keep them in `sourcesContent`. */
3345const CLIENT_MARKER = 'SOURCEMAP_MARKER_CLIENT' ;
3446const SERVER_MARKER = 'SOURCEMAP_MARKER_SERVER' ;
3547
3648const UUID_REGEX = / ^ [ \d a - f ] { 8 } - [ \d a - f ] { 4 } - [ \d a - f ] { 4 } - [ \d a - f ] { 4 } - [ \d a - f ] { 12 } $ / i;
3749
50+ /** Some presets write the server into the client output, e.g. Cloudflare Pages. */
51+ function isClientFile ( file : string ) : boolean {
52+ const relativePath = path . relative ( SERVER_OUTPUT , file ) ;
53+ return relativePath . startsWith ( '..' ) || path . isAbsolute ( relativePath ) ;
54+ }
55+
3856function filesContaining ( dir : string , needle : string ) : string [ ] {
3957 return fs
4058 . readdirSync ( dir , { recursive : true , withFileTypes : true } )
@@ -64,7 +82,7 @@ function debugIdsOfChunksWithoutSourceMap(dir: string): Set<string> {
6482}
6583
6684console . log (
67- `Variant: ${ isStaticBuild ? 'nuxt generate' : 'nuxt build' } , ` +
85+ `Variant: ${ isStaticBuild ? 'nuxt generate' : 'nuxt build' } , Nitro preset ${ nitroPreset } , ` +
6886 `client source maps ${ keepClientSourceMaps ? 'kept' : 'deleted' } \n` ,
6987) ;
7088
@@ -218,7 +236,7 @@ console.log('');
218236
219237// --- What the build leaves behind in the client output ---
220238
221- const clientSourceMaps = findSourceMapFiles ( { outputDir : CLIENT_OUTPUT } ) ;
239+ const clientSourceMaps = findSourceMapFiles ( { outputDir : CLIENT_OUTPUT } ) . filter ( isClientFile ) ;
222240
223241if ( keepClientSourceMaps ) {
224242 assert . ok ( clientSourceMaps . length > 0 , `Expected Sentry to leave the user-enabled maps in ${ CLIENT_OUTPUT } ` ) ;
@@ -228,20 +246,30 @@ if (keepClientSourceMaps) {
228246 assert . deepEqual ( clientSourceMaps , [ ] , `Expected no source maps in ${ CLIENT_OUTPUT } after upload` ) ;
229247
230248 // The maps are gone, so a surviving reference only 404s in devtools and leaks where they were.
231- const danglingReferences = findSourceMappingUrlComments ( { outputDir : CLIENT_OUTPUT } ) ;
249+ const danglingReferences = findSourceMappingUrlComments ( { outputDir : CLIENT_OUTPUT } ) . filter ( isClientFile ) ;
232250 assert . deepEqual ( danglingReferences , [ ] , `Expected no sourceMappingURL comments in ${ CLIENT_OUTPUT } ` ) ;
233251
234252 // Catches source maps inlined as `data:` URIs, which the reference check above skips by design.
235- const leakedSource = filesContaining ( CLIENT_OUTPUT , CLIENT_MARKER ) ;
253+ const leakedSource = filesContaining ( CLIENT_OUTPUT , CLIENT_MARKER ) . filter ( isClientFile ) ;
236254 assert . deepEqual ( leakedSource , [ ] , `Expected no original client source under ${ CLIENT_OUTPUT } ` ) ;
237255
238256 console . log ( ` ${ CLIENT_OUTPUT } is free of source maps, sourceMappingURL comments and original source\n` ) ;
239257}
240258
241- // --- What the built server answers for the client source maps ---
259+ // --- What the build leaves behind in the server output ---
242260
243- // `nuxt generate` emits no server, and a static host serves only the files that exist .
261+ // Nuxt enables the server maps by default, so they are the user's and Sentry must keep them .
244262if ( ! isStaticBuild ) {
263+ const serverSourceMaps = findSourceMapFiles ( { outputDir : SERVER_OUTPUT } ) ;
264+ assert . ok ( serverSourceMaps . length > 0 , `Expected Sentry to keep the server source maps in ${ SERVER_OUTPUT } ` ) ;
265+ console . log ( ` ${ serverSourceMaps . length } source map(s) kept in ${ SERVER_OUTPUT } , as Nuxt enables them\n` ) ;
266+ }
267+
268+ // --- What the built server answers for the client source maps ---
269+
270+ // `nuxt generate` emits no server, and a static host serves only the files that exist. The other presets build a
271+ // server for their platform, which Node cannot start.
272+ if ( ! isStaticBuild && nitroPreset === 'node-server' ) {
245273 const clientChunkUrls = fs
246274 . readdirSync ( CLIENT_OUTPUT , { recursive : true , withFileTypes : true } )
247275 . filter ( entry => entry . isFile ( ) && entry . name . endsWith ( '.js' ) )
0 commit comments