Skip to content

Commit 10d5454

Browse files
authored
feat(nextjs): Add disableSentryWebpackConfig flag (#17013)
1 parent fa210ad commit 10d5454

File tree

3 files changed

+140
-3
lines changed

3 files changed

+140
-3
lines changed

packages/nextjs/src/config/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,18 @@ export type SentryBuildOptions = {
486486
*/
487487
disableManifestInjection?: boolean;
488488

489+
/**
490+
* Disables automatic injection of Sentry's Webpack configuration.
491+
*
492+
* By default, the Sentry Next.js SDK injects its own Webpack configuration to enable features such as
493+
* source map upload and automatic instrumentation. Set this option to `true` if you want to prevent
494+
* the SDK from modifying your Webpack config (for example, if you want to handle Sentry integration manually
495+
* or if you are on an older version of Next.js while using Turbopack).
496+
*
497+
* @default false
498+
*/
499+
disableSentryWebpackConfig?: boolean;
500+
489501
/**
490502
* Contains a set of experimental flags that might change in future releases. These flags enable
491503
* features that are still in development and may be modified, renamed, or removed without notice.

packages/nextjs/src/config/withSentryConfig.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,10 @@ function getFinalConfigObject(
311311
],
312312
},
313313
}),
314-
webpack: !isTurbopack
315-
? constructWebpackConfigFunction(incomingUserNextConfigObject, userSentryOptions, releaseName, routeManifest)
316-
: undefined,
314+
webpack:
315+
isTurbopack || userSentryOptions.disableSentryWebpackConfig
316+
? incomingUserNextConfigObject.webpack // just return the original webpack config
317+
: constructWebpackConfigFunction(incomingUserNextConfigObject, userSentryOptions, releaseName, routeManifest),
317318
...(isTurbopackSupported && isTurbopack
318319
? {
319320
turbopack: constructTurbopackConfig({

packages/nextjs/test/config/withSentryConfig.test.ts

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,130 @@ describe('withSentryConfig', () => {
145145
});
146146
});
147147

148+
describe('webpack configuration behavior', () => {
149+
const originalTurbopack = process.env.TURBOPACK;
150+
151+
afterEach(() => {
152+
vi.restoreAllMocks();
153+
process.env.TURBOPACK = originalTurbopack;
154+
});
155+
156+
it('uses constructed webpack function when Turbopack is disabled and disableSentryWebpackConfig is false/undefined', () => {
157+
delete process.env.TURBOPACK;
158+
159+
// default behavior
160+
const finalConfigUndefined = materializeFinalNextConfig(exportedNextConfig);
161+
expect(finalConfigUndefined.webpack).toBeInstanceOf(Function);
162+
163+
const sentryOptions = {
164+
disableSentryWebpackConfig: false,
165+
};
166+
const finalConfigFalse = materializeFinalNextConfig(exportedNextConfig, undefined, sentryOptions);
167+
expect(finalConfigFalse.webpack).toBeInstanceOf(Function);
168+
});
169+
170+
it('preserves original webpack config when disableSentryWebpackConfig is true (regardless of Turbopack)', () => {
171+
const originalWebpackFunction = vi.fn();
172+
const configWithWebpack = {
173+
...exportedNextConfig,
174+
webpack: originalWebpackFunction,
175+
};
176+
177+
const sentryOptions = {
178+
disableSentryWebpackConfig: true,
179+
};
180+
181+
delete process.env.TURBOPACK;
182+
const finalConfigWithoutTurbopack = materializeFinalNextConfig(configWithWebpack, undefined, sentryOptions);
183+
expect(finalConfigWithoutTurbopack.webpack).toBe(originalWebpackFunction);
184+
185+
process.env.TURBOPACK = '1';
186+
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.3.0');
187+
const finalConfigWithTurbopack = materializeFinalNextConfig(configWithWebpack, undefined, sentryOptions);
188+
expect(finalConfigWithTurbopack.webpack).toBe(originalWebpackFunction);
189+
});
190+
191+
it('preserves original webpack config when Turbopack is enabled (ignores disableSentryWebpackConfig flag)', () => {
192+
process.env.TURBOPACK = '1';
193+
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.3.0');
194+
195+
const originalWebpackFunction = vi.fn();
196+
const configWithWebpack = {
197+
...exportedNextConfig,
198+
webpack: originalWebpackFunction,
199+
};
200+
201+
const sentryOptionsWithFalse = {
202+
disableSentryWebpackConfig: false,
203+
};
204+
const finalConfigWithFalse = materializeFinalNextConfig(configWithWebpack, undefined, sentryOptionsWithFalse);
205+
expect(finalConfigWithFalse.webpack).toBe(originalWebpackFunction);
206+
207+
const finalConfigWithUndefined = materializeFinalNextConfig(configWithWebpack);
208+
expect(finalConfigWithUndefined.webpack).toBe(originalWebpackFunction);
209+
210+
const sentryOptionsWithTrue = {
211+
disableSentryWebpackConfig: true,
212+
};
213+
const finalConfigWithTrue = materializeFinalNextConfig(configWithWebpack, undefined, sentryOptionsWithTrue);
214+
expect(finalConfigWithTrue.webpack).toBe(originalWebpackFunction);
215+
});
216+
217+
it('preserves original webpack config when Turbopack is enabled and disableSentryWebpackConfig is true', () => {
218+
process.env.TURBOPACK = '1';
219+
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.3.0');
220+
221+
const sentryOptions = {
222+
disableSentryWebpackConfig: true,
223+
};
224+
225+
const originalWebpackFunction = vi.fn();
226+
const configWithWebpack = {
227+
...exportedNextConfig,
228+
webpack: originalWebpackFunction,
229+
};
230+
231+
const finalConfig = materializeFinalNextConfig(configWithWebpack, undefined, sentryOptions);
232+
233+
expect(finalConfig.webpack).toBe(originalWebpackFunction);
234+
});
235+
236+
it('preserves undefined webpack when Turbopack is enabled, disableSentryWebpackConfig is true, and no original webpack config exists', () => {
237+
process.env.TURBOPACK = '1';
238+
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.3.0');
239+
240+
const sentryOptions = {
241+
disableSentryWebpackConfig: true,
242+
};
243+
244+
const configWithoutWebpack = {
245+
...exportedNextConfig,
246+
};
247+
delete configWithoutWebpack.webpack;
248+
249+
const finalConfig = materializeFinalNextConfig(configWithoutWebpack, undefined, sentryOptions);
250+
251+
expect(finalConfig.webpack).toBeUndefined();
252+
});
253+
254+
it('includes turbopack config when Turbopack is supported and enabled', () => {
255+
process.env.TURBOPACK = '1';
256+
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.3.0');
257+
258+
const finalConfig = materializeFinalNextConfig(exportedNextConfig);
259+
260+
expect(finalConfig.turbopack).toBeDefined();
261+
});
262+
263+
it('does not include turbopack config when Turbopack is not enabled', () => {
264+
delete process.env.TURBOPACK;
265+
266+
const finalConfig = materializeFinalNextConfig(exportedNextConfig);
267+
268+
expect(finalConfig.turbopack).toBeUndefined();
269+
});
270+
});
271+
148272
describe('release injection behavior', () => {
149273
afterEach(() => {
150274
vi.restoreAllMocks();

0 commit comments

Comments
 (0)