From c811a5ac5e619a090bfc3b7714f838d29b48f5d8 Mon Sep 17 00:00:00 2001 From: Katie Byers Date: Tue, 2 Aug 2022 22:09:04 -0700 Subject: [PATCH 1/4] create separate types for before and after deleting `sentry` property --- packages/nextjs/src/config/index.ts | 10 +++++++--- packages/nextjs/src/config/types.ts | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/nextjs/src/config/index.ts b/packages/nextjs/src/config/index.ts index dacb9adc2b4c..43da68e3df6b 100644 --- a/packages/nextjs/src/config/index.ts +++ b/packages/nextjs/src/config/index.ts @@ -16,13 +16,15 @@ export function withSentryConfig( // `defaults` in order to pass them along to the user's function if (typeof exportedUserNextConfig === 'function') { return function (phase: string, defaults: { defaultConfig: NextConfigObject }): NextConfigObject { - const userNextConfigObject = exportedUserNextConfig(phase, defaults); + let userNextConfigObject = exportedUserNextConfig(phase, defaults); // Next 12.2.3+ warns about non-canonical properties on `userNextConfig`, so grab and then remove the `sentry` // property there. Where we actually need it is in the webpack config function we're going to create, so pass it // to `constructWebpackConfigFunction` so that it will be in the created function's closure. const { sentry: userSentryOptions } = userNextConfigObject; delete userNextConfigObject.sentry; + // Remind TS that there's now no `sentry` property + userNextConfigObject = userNextConfigObject as NextConfigObject; return { ...userNextConfigObject, @@ -41,9 +43,11 @@ export function withSentryConfig( // for a more thorough explanation of what we're doing here.) const { sentry: userSentryOptions } = exportedUserNextConfig; delete exportedUserNextConfig.sentry; + // Remind TS that there's now no `sentry` property + const userNextConfigObject = exportedUserNextConfig as NextConfigObject; return { - ...exportedUserNextConfig, - webpack: constructWebpackConfigFunction(exportedUserNextConfig, userSentryWebpackPluginOptions, userSentryOptions), + ...userNextConfigObject, + webpack: constructWebpackConfigFunction(userNextConfigObject, userSentryWebpackPluginOptions, userSentryOptions), }; } diff --git a/packages/nextjs/src/config/types.ts b/packages/nextjs/src/config/types.ts index 17ccbe12a5f0..2a5ee51d9d57 100644 --- a/packages/nextjs/src/config/types.ts +++ b/packages/nextjs/src/config/types.ts @@ -8,7 +8,18 @@ export type SentryWebpackPlugin = WebpackPluginInstance & { options: SentryWebpa * Overall Nextjs config */ -export type ExportedNextConfig = NextConfigObject | NextConfigFunction; +// The first argument to `withSentryConfig` (which is the user's next config) may contain a `sentry` key, which we'll +// remove once we've captured it, in order to prevent nextjs from throwing warnings. Since it's only in there +// temporarily, we don't include it in the main `NextConfigObject` or `NextConfigFunction` types. +export type ExportedNextConfig = NextConfigObjectWithSentry | NextConfigFunctionWithSentry; + +export type NextConfigObjectWithSentry = NextConfigObject & { + sentry?: UserSentryOptions; +}; +export type NextConfigFunctionWithSentry = ( + phase: string, + defaults: { defaultConfig: NextConfigObject }, +) => NextConfigObjectWithSentry; export type NextConfigObject = { // custom webpack options @@ -21,7 +32,6 @@ export type NextConfigObject = { basePath?: string; // config which will be available at runtime publicRuntimeConfig?: { [key: string]: unknown }; - sentry?: UserSentryOptions; }; export type UserSentryOptions = { From 047a38e558701119c42fd0b754f7eff207343072 Mon Sep 17 00:00:00 2001 From: Katie Byers Date: Tue, 2 Aug 2022 22:09:54 -0700 Subject: [PATCH 2/4] pull `transpileClientSDK` option from correct location --- packages/nextjs/src/config/webpack.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index ecbbe226a12b..04346de8b7c5 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -80,7 +80,7 @@ export function constructWebpackConfigFunction( // who want to support such browsers, `transpileClientSDK` allows them to force the SDK code to go through the same // transpilation that their code goes through. We don't turn this on by default because it increases bundle size // fairly massively. - if (!isServer && userNextConfig.sentry?.transpileClientSDK) { + if (!isServer && userSentryOptions?.transpileClientSDK) { // Find all loaders which apply transpilation to user code const transpilationRules = findTranspilationRules(newConfig.module?.rules, projectDir); From 47c8daca34739959a89e26aaf5edde4238e24688 Mon Sep 17 00:00:00 2001 From: Katie Byers Date: Wed, 3 Aug 2022 15:49:47 -0700 Subject: [PATCH 3/4] fix tests --- packages/nextjs/test/config.test.ts | 177 ++++++++++++++++------------ 1 file changed, 99 insertions(+), 78 deletions(-) diff --git a/packages/nextjs/test/config.test.ts b/packages/nextjs/test/config.test.ts index a42209501a5a..d5b860abff82 100644 --- a/packages/nextjs/test/config.test.ts +++ b/packages/nextjs/test/config.test.ts @@ -10,6 +10,7 @@ import { EntryPropertyFunction, ExportedNextConfig, NextConfigObject, + NextConfigObjectWithSentry, SentryWebpackPluginOptions, WebpackConfigObject, } from '../src/config/types'; @@ -37,6 +38,9 @@ const mockExistsSync = (path: fs.PathLike) => { }; const exitsSync = jest.spyOn(fs, 'existsSync').mockImplementation(mockExistsSync); +/** Mocking of temporary directory creation (so that we have a place to stick files (like `sentry.client.config.js`) in + * order to test that we can find them) */ + // Make it so that all temporary folders, either created directly by tests or by the code they're testing, will go into // one spot that we know about, which we can then clean up when we're done const realTmpdir = jest.requireActual('os').tmpdir; @@ -63,19 +67,22 @@ afterEach(() => { mkdtempSyncSpy.mockClear(); }); -/** Mocks of the arguments passed to `withSentryConfig` */ +/** Mock next config object */ const userNextConfig: NextConfigObject = { publicRuntimeConfig: { location: 'dogpark', activities: ['fetch', 'chasing', 'digging'] }, - webpack: (config: WebpackConfigObject, _options: BuildContext) => ({ - ...config, + webpack: (incomingWebpackConfig: WebpackConfigObject, _options: BuildContext) => ({ + ...incomingWebpackConfig, mode: 'universal-sniffing', entry: async () => Promise.resolve({ - ...(await (config.entry as EntryPropertyFunction)()), + ...(await (incomingWebpackConfig.entry as EntryPropertyFunction)()), simulatorBundle: './src/simulator/index.ts', }), }), }; + +/** Mocks of the arguments passed to `withSentryConfig` */ +const exportedNextConfig = userNextConfig as NextConfigObjectWithSentry; const userSentryWebpackPluginConfig = { org: 'squirrelChasers', project: 'simulator' }; process.env.SENTRY_AUTH_TOKEN = 'dogsarebadatkeepingsecrets'; process.env.SENTRY_RELEASE = 'doGsaREgReaT'; @@ -119,12 +126,12 @@ const clientWebpackConfig = { context: '/Users/Maisey/projects/squirrelChasingSimulator', }; -// In real life, next will copy the `userNextConfig` into the `buildContext`. Since we're providing mocks for both of -// those, we need to mimic that behavior, and since `userNextConfig` can vary per test, we need to have the option do it -// dynamically. +// In real life, next will copy the `exportedNextConfig` (materializing it first, if it's a function) into the +// `buildContext`. Since we're providing mocks for both of those, we need to mimic that behavior, and since +// `exportedNextConfig` can vary per test, we need to have the option do it dynamically. function getBuildContext( buildTarget: 'server' | 'client', - userNextConfig: NextConfigObject, + exportedNextConfig: ExportedNextConfig, webpackVersion: string = '5.4.15', ): BuildContext { return { @@ -135,31 +142,31 @@ function getBuildContext( // nextjs's default values target: 'server', distDir: '.next', - ...userNextConfig, + ...exportedNextConfig, } as NextConfigObject, webpack: { version: webpackVersion }, isServer: buildTarget === 'server', }; } -const serverBuildContext = getBuildContext('server', userNextConfig); -const clientBuildContext = getBuildContext('client', userNextConfig); +const serverBuildContext = getBuildContext('server', exportedNextConfig); +const clientBuildContext = getBuildContext('client', exportedNextConfig); /** * 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 exportedNextConfig Next config options provided by the user * @param userSentryWebpackPluginConfig SentryWebpackPlugin options provided by the user * * @returns The config values next will receive directly from `withSentryConfig` or when it calls the function returned * by `withSentryConfig` */ function materializeFinalNextConfig( - userNextConfig: ExportedNextConfig, + exportedNextConfig: ExportedNextConfig, userSentryWebpackPluginConfig?: Partial, ): NextConfigObject { - const sentrifiedConfig = withSentryConfig(userNextConfig, userSentryWebpackPluginConfig); + const sentrifiedConfig = withSentryConfig(exportedNextConfig, userSentryWebpackPluginConfig); let finalConfigValues = sentrifiedConfig; if (typeof sentrifiedConfig === 'function') { @@ -177,7 +184,7 @@ function materializeFinalNextConfig( * that. * * @param options An object including the following: - * - `userNextConfig` Next config options provided by the user + * - `exportedNextConfig` Next config options provided by the user * - `userSentryWebpackPluginConfig` SentryWebpackPlugin options provided by the user * - `incomingWebpackConfig` The existing webpack config, passed to the function as `config` * - `incomingWebpackBuildContext` The existing webpack build context, passed to the function as `options` @@ -185,22 +192,29 @@ function materializeFinalNextConfig( * @returns The webpack config values next will use when it calls the function that `createFinalWebpackConfig` returns */ async function materializeFinalWebpackConfig(options: { - userNextConfig: ExportedNextConfig; + exportedNextConfig: ExportedNextConfig; userSentryWebpackPluginConfig?: Partial; incomingWebpackConfig: WebpackConfigObject; incomingWebpackBuildContext: BuildContext; }): Promise { - const { userNextConfig, userSentryWebpackPluginConfig, incomingWebpackConfig, incomingWebpackBuildContext } = options; + const { exportedNextConfig, userSentryWebpackPluginConfig, incomingWebpackConfig, incomingWebpackBuildContext } = + options; // if the user's next config is a function, run it so we have access to the values const materializedUserNextConfig = - typeof userNextConfig === 'function' ? userNextConfig('phase-production-build', defaultsObject) : userNextConfig; + typeof exportedNextConfig === 'function' + ? exportedNextConfig('phase-production-build', defaultsObject) + : exportedNextConfig; + + // extract the `sentry` property as we do in `withSentryConfig` + const { sentry: sentryConfig } = materializedUserNextConfig; + delete materializedUserNextConfig.sentry; // get the webpack config function we'd normally pass back to next const webpackConfigFunction = constructWebpackConfigFunction( materializedUserNextConfig, userSentryWebpackPluginConfig, - materializedUserNextConfig.sentry, + sentryConfig, ); // call it to get concrete values for comparison @@ -221,7 +235,7 @@ export function findWebpackPlugin( describe('withSentryConfig', () => { it('includes expected properties', () => { - const finalConfig = materializeFinalNextConfig(userNextConfig); + const finalConfig = materializeFinalNextConfig(exportedNextConfig); expect(finalConfig).toEqual( expect.objectContaining({ @@ -231,13 +245,13 @@ describe('withSentryConfig', () => { }); it('preserves unrelated next config options', () => { - const finalConfig = materializeFinalNextConfig(userNextConfig); + const finalConfig = materializeFinalNextConfig(exportedNextConfig); expect(finalConfig.publicRuntimeConfig).toEqual(userNextConfig.publicRuntimeConfig); }); it("works when user's overall config is an object", () => { - const finalConfig = materializeFinalNextConfig(userNextConfig); + const finalConfig = materializeFinalNextConfig(exportedNextConfig); expect(finalConfig).toEqual( expect.objectContaining({ @@ -248,31 +262,32 @@ describe('withSentryConfig', () => { }); it("works when user's overall config is a function", () => { - const userNextConfigFunction = () => userNextConfig; + const exportedNextConfigFunction = () => userNextConfig; - const finalConfig = materializeFinalNextConfig(userNextConfigFunction); + const finalConfig = materializeFinalNextConfig(exportedNextConfigFunction); expect(finalConfig).toEqual( expect.objectContaining({ - ...userNextConfigFunction(), + ...exportedNextConfigFunction(), webpack: expect.any(Function), // `webpack` is tested specifically elsewhere }), ); }); it('correctly passes `phase` and `defaultConfig` through to functional `userNextConfig`', () => { - const userNextConfigFunction = jest.fn().mockReturnValue(userNextConfig); + const exportedNextConfigFunction = jest.fn().mockReturnValue(userNextConfig); - materializeFinalNextConfig(userNextConfigFunction); + materializeFinalNextConfig(exportedNextConfigFunction); - expect(userNextConfigFunction).toHaveBeenCalledWith(runtimePhase, defaultsObject); + expect(exportedNextConfigFunction).toHaveBeenCalledWith(runtimePhase, defaultsObject); + }); }); }); describe('webpack config', () => { it('includes expected properties', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContext, }); @@ -288,7 +303,7 @@ describe('webpack config', () => { it('preserves unrelated webpack config options', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContext, }); @@ -303,17 +318,19 @@ describe('webpack config', () => { }); it('allows for the use of `hidden-source-map` as `devtool` value for client-side builds', async () => { - const userNextConfigHiddenSourceMaps = { ...userNextConfig, sentry: { ...userNextConfig.sentry } }; - userNextConfigHiddenSourceMaps.sentry.hideSourceMaps = true; + const exportedNextConfigHiddenSourceMaps = { + ...exportedNextConfig, + sentry: { ...exportedNextConfig.sentry, hideSourceMaps: true }, + }; const finalClientWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig: userNextConfigHiddenSourceMaps, + exportedNextConfig: exportedNextConfigHiddenSourceMaps, incomingWebpackConfig: clientWebpackConfig, incomingWebpackBuildContext: clientBuildContext, }); const finalServerWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig: userNextConfigHiddenSourceMaps, + exportedNextConfig: exportedNextConfigHiddenSourceMaps, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContext, }); @@ -328,7 +345,7 @@ describe('webpack config', () => { it('handles various entrypoint shapes', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContext, }); @@ -371,12 +388,12 @@ describe('webpack config', () => { it('injects user config file into `_app` in both server and client bundles', async () => { const finalServerWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContext, }); const finalClientWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: clientWebpackConfig, incomingWebpackBuildContext: clientBuildContext, }); @@ -395,12 +412,12 @@ describe('webpack config', () => { it('injects user config file into `_error` in server bundle but not client bundle', async () => { const finalServerWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContext, }); const finalClientWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: clientWebpackConfig, incomingWebpackBuildContext: clientBuildContext, }); @@ -419,7 +436,7 @@ describe('webpack config', () => { it('injects user config file into API routes', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContext, }); @@ -443,7 +460,7 @@ describe('webpack config', () => { it('does not inject user config file into API middleware', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContext, }); @@ -458,7 +475,7 @@ describe('webpack config', () => { it('does not inject anything into non-_app, non-_error, non-API routes', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: clientWebpackConfig, incomingWebpackBuildContext: clientBuildContext, }); @@ -475,7 +492,7 @@ describe('webpack config', () => { describe('webpack loaders', () => { it('adds loader to server config', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContext, }); @@ -499,7 +516,7 @@ describe('webpack config', () => { it("doesn't add loader to client config", async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: clientWebpackConfig, incomingWebpackBuildContext: clientBuildContext, }); @@ -521,7 +538,7 @@ describe('Sentry webpack plugin config', () => { it('includes expected properties', async () => { // also, can pull from either env or user config (see notes on specific properties below) const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, userSentryWebpackPluginConfig, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContext, @@ -546,7 +563,7 @@ describe('Sentry webpack plugin config', () => { it('preserves unrelated plugin config options', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, userSentryWebpackPluginConfig: { ...userSentryWebpackPluginConfig, debug: true }, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContext, @@ -567,7 +584,7 @@ describe('Sentry webpack plugin config', () => { describe('Sentry webpack plugin `include` option', () => { it('has the correct value when building client bundles', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: clientWebpackConfig, incomingWebpackBuildContext: clientBuildContext, }); @@ -583,11 +600,11 @@ describe('Sentry webpack plugin config', () => { }); it('has the correct value when building client bundles using `widenClientFileUpload` option', async () => { - const userNextConfigWithWidening = { ...userNextConfig, sentry: { widenClientFileUpload: true } }; + const exportedNextConfigWithWidening = { ...exportedNextConfig, sentry: { widenClientFileUpload: true } }; const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig: userNextConfigWithWidening, + exportedNextConfig: exportedNextConfigWithWidening, incomingWebpackConfig: clientWebpackConfig, - incomingWebpackBuildContext: getBuildContext('client', userNextConfigWithWidening), + incomingWebpackBuildContext: getBuildContext('client', exportedNextConfigWithWidening), }); const sentryWebpackPluginInstance = findWebpackPlugin( @@ -601,13 +618,15 @@ describe('Sentry webpack plugin config', () => { }); it('has the correct value when building serverless server bundles', async () => { - const userNextConfigServerless = { ...userNextConfig }; - userNextConfigServerless.target = 'experimental-serverless-trace'; + const exportedNextConfigServerless = { + ...exportedNextConfig, + target: 'experimental-serverless-trace' as const, + }; const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig: userNextConfigServerless, + exportedNextConfig: exportedNextConfigServerless, incomingWebpackConfig: serverWebpackConfig, - incomingWebpackBuildContext: getBuildContext('server', userNextConfigServerless), + incomingWebpackBuildContext: getBuildContext('server', exportedNextConfigServerless), }); const sentryWebpackPluginInstance = findWebpackPlugin( @@ -621,11 +640,11 @@ describe('Sentry webpack plugin config', () => { }); it('has the correct value when building serverful server bundles using webpack 4', async () => { - const serverBuildContextWebpack4 = getBuildContext('server', userNextConfig); + const serverBuildContextWebpack4 = getBuildContext('server', exportedNextConfig); serverBuildContextWebpack4.webpack.version = '4.15.13'; const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContextWebpack4, }); @@ -642,7 +661,7 @@ describe('Sentry webpack plugin config', () => { it('has the correct value when building serverful server bundles using webpack 5', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContext, }); @@ -662,7 +681,7 @@ describe('Sentry webpack plugin config', () => { describe('Sentry webpack plugin `ignore` option', () => { it('has the correct value when building client bundles', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig, + exportedNextConfig, incomingWebpackConfig: clientWebpackConfig, incomingWebpackBuildContext: clientBuildContext, }); @@ -676,11 +695,11 @@ describe('Sentry webpack plugin config', () => { }); it('has the correct value when building client bundles using `widenClientFileUpload` option', async () => { - const userNextConfigWithWidening = { ...userNextConfig, sentry: { widenClientFileUpload: true } }; + const exportedNextConfigWithWidening = { ...exportedNextConfig, sentry: { widenClientFileUpload: true } }; const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig: userNextConfigWithWidening, + exportedNextConfig: exportedNextConfigWithWidening, incomingWebpackConfig: clientWebpackConfig, - incomingWebpackBuildContext: getBuildContext('client', userNextConfigWithWidening), + incomingWebpackBuildContext: getBuildContext('client', exportedNextConfigWithWidening), }); const sentryWebpackPluginInstance = findWebpackPlugin( @@ -699,16 +718,16 @@ describe('Sentry webpack plugin config', () => { }); describe("Sentry webpack plugin `include` option with basePath filled on next's config", () => { - const userNextConfigWithBasePath = { - ...userNextConfig, + const exportedNextConfigWithBasePath = { + ...exportedNextConfig, basePath: '/city-park', }; it('has the correct value when building client bundles', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig: userNextConfigWithBasePath, + exportedNextConfig: exportedNextConfigWithBasePath, incomingWebpackConfig: clientWebpackConfig, - incomingWebpackBuildContext: getBuildContext('client', userNextConfigWithBasePath), + incomingWebpackBuildContext: getBuildContext('client', exportedNextConfigWithBasePath), }); const sentryWebpackPluginInstance = findWebpackPlugin( @@ -722,13 +741,15 @@ describe('Sentry webpack plugin config', () => { }); it('has the correct value when building serverless server bundles', async () => { - const userNextConfigServerless = { ...userNextConfigWithBasePath }; - userNextConfigServerless.target = 'experimental-serverless-trace'; + const exportedNextConfigServerless = { + ...exportedNextConfigWithBasePath, + target: 'experimental-serverless-trace' as const, + }; const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig: userNextConfigServerless, + exportedNextConfig: exportedNextConfigServerless, incomingWebpackConfig: serverWebpackConfig, - incomingWebpackBuildContext: getBuildContext('server', userNextConfigServerless), + incomingWebpackBuildContext: getBuildContext('server', exportedNextConfigServerless), }); const sentryWebpackPluginInstance = findWebpackPlugin( @@ -742,11 +763,11 @@ describe('Sentry webpack plugin config', () => { }); it('has the correct value when building serverful server bundles using webpack 4', async () => { - const serverBuildContextWebpack4 = getBuildContext('server', userNextConfigWithBasePath); + const serverBuildContextWebpack4 = getBuildContext('server', exportedNextConfigWithBasePath); serverBuildContextWebpack4.webpack.version = '4.15.13'; const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig: userNextConfigWithBasePath, + exportedNextConfig: exportedNextConfigWithBasePath, incomingWebpackConfig: serverWebpackConfig, incomingWebpackBuildContext: serverBuildContextWebpack4, }); @@ -763,9 +784,9 @@ describe('Sentry webpack plugin config', () => { it('has the correct value when building serverful server bundles using webpack 5', async () => { const finalWebpackConfig = await materializeFinalWebpackConfig({ - userNextConfig: userNextConfigWithBasePath, + exportedNextConfig: exportedNextConfigWithBasePath, incomingWebpackConfig: serverWebpackConfig, - incomingWebpackBuildContext: getBuildContext('server', userNextConfigWithBasePath), + incomingWebpackBuildContext: getBuildContext('server', exportedNextConfigWithBasePath), }); const sentryWebpackPluginInstance = findWebpackPlugin( @@ -782,12 +803,12 @@ describe('Sentry webpack plugin config', () => { it('allows SentryWebpackPlugin to be turned off for client code (independent of server code)', () => { const clientFinalNextConfig = materializeFinalNextConfig({ - ...userNextConfig, + ...exportedNextConfig, sentry: { disableClientWebpackPlugin: true }, }); const clientFinalWebpackConfig = clientFinalNextConfig.webpack?.(clientWebpackConfig, clientBuildContext); - const serverFinalNextConfig = materializeFinalNextConfig(userNextConfig, userSentryWebpackPluginConfig); + const serverFinalNextConfig = materializeFinalNextConfig(exportedNextConfig, userSentryWebpackPluginConfig); const serverFinalWebpackConfig = serverFinalNextConfig.webpack?.(serverWebpackConfig, serverBuildContext); expect(clientFinalWebpackConfig?.plugins).not.toEqual(expect.arrayContaining([expect.any(SentryWebpackPlugin)])); @@ -796,12 +817,12 @@ describe('Sentry webpack plugin config', () => { it('allows SentryWebpackPlugin to be turned off for server code (independent of client code)', () => { const serverFinalNextConfig = materializeFinalNextConfig({ - ...userNextConfig, + ...exportedNextConfig, sentry: { disableServerWebpackPlugin: true }, }); const serverFinalWebpackConfig = serverFinalNextConfig.webpack?.(serverWebpackConfig, serverBuildContext); - const clientFinalNextConfig = materializeFinalNextConfig(userNextConfig, userSentryWebpackPluginConfig); + const clientFinalNextConfig = materializeFinalNextConfig(exportedNextConfig, userSentryWebpackPluginConfig); const clientFinalWebpackConfig = clientFinalNextConfig.webpack?.(clientWebpackConfig, clientBuildContext); expect(serverFinalWebpackConfig?.plugins).not.toEqual(expect.arrayContaining([expect.any(SentryWebpackPlugin)])); @@ -810,7 +831,7 @@ describe('Sentry webpack plugin config', () => { it("doesn't set devtool if webpack plugin is disabled", () => { const finalNextConfig = materializeFinalNextConfig({ - ...userNextConfig, + ...exportedNextConfig, webpack: () => ({ devtool: 'something-besides-source-map' } as any), sentry: { disableServerWebpackPlugin: true }, }); From 4481089f36ebb605adac2c07beeb517c079a9a5f Mon Sep 17 00:00:00 2001 From: Katie Byers Date: Wed, 3 Aug 2022 15:49:56 -0700 Subject: [PATCH 4/4] add test for removing sentry --- packages/nextjs/test/config.test.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/nextjs/test/config.test.ts b/packages/nextjs/test/config.test.ts index d5b860abff82..1b44c53527cc 100644 --- a/packages/nextjs/test/config.test.ts +++ b/packages/nextjs/test/config.test.ts @@ -281,6 +281,15 @@ describe('withSentryConfig', () => { expect(exportedNextConfigFunction).toHaveBeenCalledWith(runtimePhase, defaultsObject); }); + + it('removes `sentry` property', () => { + // It's unclear why we need this cast - + const finalConfig = materializeFinalNextConfig({ ...exportedNextConfig, sentry: {} }); + // const finalConfig = materializeFinalNextConfig({ ...exportedNextConfig, sentry: {} } as ExportedNextConfig); + + // We have to check using `in` because TS knows it shouldn't be there and throws a type error if we try to access it + // directly + expect('sentry' in finalConfig).toBe(false); }); });