diff --git a/packages/nextjs/src/config/index.ts b/packages/nextjs/src/config/index.ts index b4ed06f41206..21beb61b482c 100644 --- a/packages/nextjs/src/config/index.ts +++ b/packages/nextjs/src/config/index.ts @@ -11,23 +11,22 @@ import { constructWebpackConfigFunction } from './webpack'; export function withSentryConfig( userNextConfig: ExportedNextConfig = {}, userSentryWebpackPluginOptions: Partial = {}, -): NextConfigFunction { - const newWebpackExport = constructWebpackConfigFunction(userNextConfig, userSentryWebpackPluginOptions); - - const finalNextConfig = ( - phase: string, - defaults: { defaultConfig: { [key: string]: unknown } }, - ): NextConfigObject => { - const materializedUserNextConfig = - typeof userNextConfig === 'function' ? userNextConfig(phase, defaults) : userNextConfig; - - return { - ...materializedUserNextConfig, - // TODO When we add a way to disable the webpack plugin, doing so should turn this off, too - productionBrowserSourceMaps: true, - webpack: newWebpackExport, - }; +): NextConfigFunction | NextConfigObject { + const partialConfig = { + // TODO When we add a way to disable the webpack plugin, doing so should turn this off, too + productionBrowserSourceMaps: true, + webpack: constructWebpackConfigFunction(userNextConfig, userSentryWebpackPluginOptions), }; - return finalNextConfig; + // If the user has passed us a function, we need to return a function, so that we have access to `phase` and + // `defaults` in order to pass them along to the user's function + if (typeof userNextConfig === 'function') { + return (phase: string, defaults: { defaultConfig: { [key: string]: unknown } }): NextConfigObject => ({ + ...userNextConfig(phase, defaults), + ...partialConfig, + }); + } + + // Otherwise, we can just merge their config with ours and return an object. + return { ...userNextConfig, ...partialConfig }; } diff --git a/packages/nextjs/test/config.test.ts b/packages/nextjs/test/config.test.ts index 4abe6c8426ce..c1d7f1ab249c 100644 --- a/packages/nextjs/test/config.test.ts +++ b/packages/nextjs/test/config.test.ts @@ -50,24 +50,31 @@ const clientWebpackConfig = { const buildContext = { isServer: true, dev: false, buildId: 'doGsaREgReaT' }; /** - * Derive the final values of all next config options, by first applying `withSentryConfig` and then running the - * resulting function. + * Derive the final values of all next config options, by first applying `withSentryConfig` and then, if it returns a + * function, running that function. * * @param userNextConfig Next config options provided by the user * @param userSentryWebpackPluginConfig SentryWebpackPlugin options provided by the user * - * @returns The config values next will receive when it calls the function returned by `withSentryConfig` + * @returns The config values next will receive directly from `withSentryConfig` or when it calls the function returned + * by `withSentryConfig` */ function materializeFinalNextConfig( userNextConfig: ExportedNextConfig, userSentryWebpackPluginConfig: SentryWebpackPluginOptions, ): NextConfigObject { - const configFunction = withSentryConfig(userNextConfig, userSentryWebpackPluginConfig); - const finalConfigValues = configFunction('phase-production-build', { - defaultConfig: {}, - }); + const sentrifiedConfig = withSentryConfig(userNextConfig, userSentryWebpackPluginConfig); + let finalConfigValues = sentrifiedConfig; + + if (typeof sentrifiedConfig === 'function') { + // for some reason TS won't recognize that `finalConfigValues` is now a NextConfigObject, which is why the cast + // below is necessary + finalConfigValues = sentrifiedConfig('phase-production-build', { + defaultConfig: {}, + }); + } - return finalConfigValues; + return finalConfigValues as NextConfigObject; } /**