@@ -23,6 +23,7 @@ import type {
2323 UserSentryOptions ,
2424 WebpackConfigFunction ,
2525 WebpackConfigObject ,
26+ WebpackConfigObjectWithModuleRules ,
2627 WebpackEntryProperty ,
2728 WebpackModuleRule ,
2829 WebpackPluginInstance ,
@@ -67,35 +68,33 @@ export function constructWebpackConfigFunction(
6768 buildContext : BuildContext ,
6869 ) : WebpackConfigObject {
6970 const { isServer, dev : isDev , dir : projectDir } = buildContext ;
70- let newConfig = { ...incomingConfig } ;
71+ let rawNewConfig = { ...incomingConfig } ;
7172
7273 // if user has custom webpack config (which always takes the form of a function), run it so we have actual values to
7374 // work with
7475 if ( 'webpack' in userNextConfig && typeof userNextConfig . webpack === 'function' ) {
75- newConfig = userNextConfig . webpack ( newConfig , buildContext ) ;
76+ rawNewConfig = userNextConfig . webpack ( rawNewConfig , buildContext ) ;
7677 }
7778
79+ // This mutates `rawNewConfig` in place, but also returns it in order to switch its type to one in which
80+ // `newConfig.module.rules` is required, so we don't have to keep asserting its existence
81+ const newConfig = setUpModuleRules ( rawNewConfig ) ;
82+
7883 if ( isServer ) {
79- newConfig . module = {
80- ...newConfig . module ,
81- rules : [
82- ...( newConfig . module ?. rules || [ ] ) ,
84+ newConfig . module . rules . push ( {
85+ test : / s e n t r y \. s e r v e r \. c o n f i g \. ( j s x ? | t s x ? ) / ,
86+ use : [
8387 {
84- test : / s e n t r y \. s e r v e r \. c o n f i g \. ( j s x ? | t s x ? ) / ,
85- use : [
86- {
87- // Support non-default output directories by making the output path (easy to get here at build-time)
88- // available to the server SDK's default `RewriteFrames` instance (which needs it at runtime), by
89- // injecting code to attach it to `global`.
90- loader : path . resolve ( __dirname , 'loaders/prefixLoader.js' ) ,
91- options : {
92- distDir : userNextConfig . distDir || '.next' ,
93- } ,
94- } ,
95- ] ,
88+ // Support non-default output directories by making the output path (easy to get here at build-time)
89+ // available to the server SDK's default `RewriteFrames` instance (which needs it at runtime), by
90+ // injecting code to attach it to `global`.
91+ loader : path . resolve ( __dirname , 'loaders/prefixLoader.js' ) ,
92+ options : {
93+ distDir : userNextConfig . distDir || '.next' ,
94+ } ,
9695 } ,
9796 ] ,
98- } ;
97+ } ) ;
9998
10099 if ( userSentryOptions . autoInstrumentServerFunctions !== false ) {
101100 const pagesDir = newConfig . resolve ?. alias ?. [ 'private-next-pages' ] as string ;
@@ -628,3 +627,20 @@ function handleSourcemapHidingOptionWarning(userSentryOptions: UserSentryOptions
628627 // );
629628 // }
630629}
630+
631+ /**
632+ * Ensure that `newConfig.module.rules` exists. Modifies the given config in place but also returns it in order to
633+ * change its type.
634+ *
635+ * @param newConfig A webpack config object which may or may not contain `module` and `module.rules`
636+ * @returns The same object, with an empty `module.rules` array added if necessary
637+ */
638+ function setUpModuleRules ( newConfig : WebpackConfigObject ) : WebpackConfigObjectWithModuleRules {
639+ newConfig . module = {
640+ ...newConfig . module ,
641+ rules : [ ...( newConfig . module ?. rules || [ ] ) ] ,
642+ } ;
643+ // Surprising that we have to assert the type here, since we've demonstrably guaranteed the existence of
644+ // `newConfig.module.rules` just above, but ¯\_(ツ)_/¯
645+ return newConfig as WebpackConfigObjectWithModuleRules ;
646+ }
0 commit comments