@@ -54,16 +54,25 @@ export function constructWebpackConfigFunction(
54
54
) : WebpackConfigObject {
55
55
const { isServer, dev : isDev , dir : projectDir } = buildContext ;
56
56
const runtime = isServer ? ( buildContext . nextRuntime === 'edge' ? 'edge' : 'server' ) : 'client' ;
57
+ // Default page extensions per https://github.com/vercel/next.js/blob/f1dbc9260d48c7995f6c52f8fbcc65f08e627992/packages/next/server/config-shared.ts#L161
58
+ const pageExtensions = userNextConfig . pageExtensions || [ 'tsx' , 'ts' , 'jsx' , 'js' ] ;
59
+ const dotPrefixedPageExtensions = pageExtensions . map ( ext => `.${ ext } ` ) ;
60
+ const pageExtensionRegex = pageExtensions . map ( escapeStringForRegex ) . join ( '|' ) ;
61
+
62
+ // We add `.ts` and `.js` back in because `pageExtensions` might not be relevant to the instrumentation file
63
+ // e.g. user's setting `.mdx`. In that case we still want to default look up
64
+ // `instrumentation.ts` and `instrumentation.js`
65
+ const instrumentationFile = getInstrumentationFile ( projectDir , dotPrefixedPageExtensions . concat ( [ '.ts' , '.js' ] ) ) ;
57
66
58
67
if ( runtime !== 'client' ) {
59
- warnAboutDeprecatedConfigFiles ( projectDir , runtime ) ;
68
+ warnAboutDeprecatedConfigFiles ( projectDir , instrumentationFile , runtime ) ;
60
69
}
61
70
if ( runtime === 'server' ) {
62
71
const nextJsVersion = getNextjsVersion ( ) ;
63
72
const { major } = parseSemver ( nextJsVersion || '' ) ;
64
73
// was added in v15 (https://github.com/vercel/next.js/pull/67539)
65
74
if ( major && major >= 15 ) {
66
- warnAboutMissingOnRequestErrorHandler ( projectDir ) ;
75
+ warnAboutMissingOnRequestErrorHandler ( instrumentationFile ) ;
67
76
}
68
77
}
69
78
@@ -110,11 +119,6 @@ export function constructWebpackConfigFunction(
110
119
? path . join ( appDirPath , '..' )
111
120
: projectDir ;
112
121
113
- // Default page extensions per https://github.com/vercel/next.js/blob/f1dbc9260d48c7995f6c52f8fbcc65f08e627992/packages/next/server/config-shared.ts#L161
114
- const pageExtensions = userNextConfig . pageExtensions || [ 'tsx' , 'ts' , 'jsx' , 'js' ] ;
115
- const dotPrefixedPageExtensions = pageExtensions . map ( ext => `.${ ext } ` ) ;
116
- const pageExtensionRegex = pageExtensions . map ( escapeStringForRegex ) . join ( '|' ) ;
117
-
118
122
const staticWrappingLoaderOptions = {
119
123
appDir : appDirPath ,
120
124
pagesDir : pagesDirPath ,
@@ -445,37 +449,29 @@ async function addSentryToClientEntryProperty(
445
449
}
446
450
447
451
/**
448
- * Make sure the instrumentation file has a `onRequestError` Handler
449
- *
450
- * @param projectDir The root directory of the project, where config files would be located
452
+ * Gets the content of the user's instrumentation file
451
453
*/
452
- function warnAboutMissingOnRequestErrorHandler ( projectDir : string ) : void {
453
- const instrumentationPaths = [
454
- [ 'src' , 'instrumentation.ts' ] ,
455
- [ 'src' , 'instrumentation.js' ] ,
456
- [ 'instrumentation.ts' ] ,
457
- [ 'instrumentation.js' ] ,
458
- ] ;
459
- const instrumentationFile = instrumentationPaths
460
- . map ( pathSegments => path . resolve ( projectDir , ...pathSegments ) )
461
- . find ( function exists ( filePath : string ) : string | null {
462
- try {
463
- fs . accessSync ( filePath , fs . constants . F_OK ) ;
464
- return filePath ;
465
- } catch ( error ) {
466
- return null ;
467
- }
468
- } ) ;
454
+ function getInstrumentationFile ( projectDir : string , dotPrefixedExtensions : string [ ] ) : string | null {
455
+ const paths = dotPrefixedExtensions . flatMap ( extension => [
456
+ [ 'src' , `instrumentation${ extension } ` ] ,
457
+ [ `instrumentation${ extension } ` ] ,
458
+ ] ) ;
469
459
470
- function hasOnRequestErrorHandler ( absolutePath : string ) : boolean {
460
+ for ( const pathSegments of paths ) {
471
461
try {
472
- const content = fs . readFileSync ( absolutePath , 'utf8' ) ;
473
- return content . includes ( 'onRequestError' ) ;
474
- } catch ( error ) {
475
- return false ;
462
+ return fs . readFileSync ( path . resolve ( projectDir , ...pathSegments ) , { encoding : 'utf-8' } ) ;
463
+ } catch ( e ) {
464
+ // no-op
476
465
}
477
466
}
478
467
468
+ return null ;
469
+ }
470
+
471
+ /**
472
+ * Make sure the instrumentation file has a `onRequestError` Handler
473
+ */
474
+ function warnAboutMissingOnRequestErrorHandler ( instrumentationFile : string | null ) : void {
479
475
if ( ! instrumentationFile ) {
480
476
if ( ! process . env . SENTRY_SUPPRESS_INSTRUMENTATION_FILE_WARNING ) {
481
477
// eslint-disable-next-line no-console
@@ -488,7 +484,7 @@ function warnAboutMissingOnRequestErrorHandler(projectDir: string): void {
488
484
return ;
489
485
}
490
486
491
- if ( ! hasOnRequestErrorHandler ( instrumentationFile ) ) {
487
+ if ( ! instrumentationFile . includes ( 'onRequestError' ) ) {
492
488
// eslint-disable-next-line no-console
493
489
console . warn (
494
490
chalk . yellow (
@@ -505,27 +501,15 @@ function warnAboutMissingOnRequestErrorHandler(projectDir: string): void {
505
501
* @param projectDir The root directory of the project, where config files would be located
506
502
* @param platform Either "server" or "edge", so that we know which file to look for
507
503
*/
508
- function warnAboutDeprecatedConfigFiles ( projectDir : string , platform : 'server' | 'edge' ) : void {
509
- const hasInstrumentationHookWithIndicationsOfSentry = [
510
- [ 'src' , 'instrumentation.ts' ] ,
511
- [ 'src' , 'instrumentation.js' ] ,
512
- [ 'instrumentation.ts' ] ,
513
- [ 'instrumentation.js' ] ,
514
- ] . some ( potentialInstrumentationHookPathSegments => {
515
- try {
516
- const instrumentationHookContent = fs . readFileSync (
517
- path . resolve ( projectDir , ...potentialInstrumentationHookPathSegments ) ,
518
- { encoding : 'utf-8' } ,
519
- ) ;
520
-
521
- return (
522
- instrumentationHookContent . includes ( '@sentry/' ) ||
523
- instrumentationHookContent . match ( / s e n t r y \. ( s e r v e r | e d g e ) \. c o n f i g ( \. ( t s | j s ) ) ? / )
524
- ) ;
525
- } catch ( e ) {
526
- return false ;
527
- }
528
- } ) ;
504
+ function warnAboutDeprecatedConfigFiles (
505
+ projectDir : string ,
506
+ instrumentationFile : string | null ,
507
+ platform : 'server' | 'edge' ,
508
+ ) : void {
509
+ const hasInstrumentationHookWithIndicationsOfSentry =
510
+ instrumentationFile &&
511
+ ( instrumentationFile . includes ( '@sentry/' ) ||
512
+ instrumentationFile . match ( / s e n t r y \. ( s e r v e r | e d g e ) \. c o n f i g ( \. ( t s | j s ) ) ? / ) ) ;
529
513
530
514
if ( hasInstrumentationHookWithIndicationsOfSentry ) {
531
515
return ;
@@ -535,7 +519,7 @@ function warnAboutDeprecatedConfigFiles(projectDir: string, platform: 'server' |
535
519
if ( fs . existsSync ( path . resolve ( projectDir , filename ) ) ) {
536
520
// eslint-disable-next-line no-console
537
521
console . warn (
538
- `[@sentry/nextjs] It appears you've configured a \`${ filename } \` file. Please ensure to put this file's content into the \`register()\` function of a Next.js instrumentation hook instead. To ensure correct functionality of the SDK, \`Sentry.init\` must be called inside \` instrumentation.ts\`. Learn more about setting up an instrumentation hook in Next.js: https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation. You can safely delete the \`${ filename } \` file afterward.` ,
522
+ `[@sentry/nextjs] It appears you've configured a \`${ filename } \` file. Please ensure to put this file's content into the \`register()\` function of a Next.js instrumentation file instead. To ensure correct functionality of the SDK, \`Sentry.init\` must be called inside of an instrumentation file. Learn more about setting up an instrumentation file in Next.js: https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation. You can safely delete the \`${ filename } \` file afterward.` ,
539
523
) ;
540
524
}
541
525
}
0 commit comments