Skip to content

Commit d324ed1

Browse files
authored
fix(nextjs): Correctly handle functional next config in withSentryConfig (#3698)
The next config provided to `withSentryConfig` can be an object or a function, but we've only been handling the first case. More details in PR description.
1 parent db1edce commit d324ed1

File tree

3 files changed

+39
-9
lines changed

3 files changed

+39
-9
lines changed

packages/nextjs/src/config/index.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ExportedNextConfig, NextConfigObject, SentryWebpackPluginOptions } from './types';
1+
import { ExportedNextConfig, NextConfigFunction, NextConfigObject, SentryWebpackPluginOptions } from './types';
22
import { constructWebpackConfigFunction } from './webpack';
33

44
/**
@@ -11,14 +11,22 @@ import { constructWebpackConfigFunction } from './webpack';
1111
export function withSentryConfig(
1212
userNextConfig: ExportedNextConfig = {},
1313
userSentryWebpackPluginOptions: Partial<SentryWebpackPluginOptions> = {},
14-
): NextConfigObject {
14+
): NextConfigFunction {
1515
const newWebpackExport = constructWebpackConfigFunction(userNextConfig, userSentryWebpackPluginOptions);
1616

17-
const finalNextConfig = {
18-
...userNextConfig,
19-
// TODO When we add a way to disable the webpack plugin, doing so should turn this off, too
20-
productionBrowserSourceMaps: true,
21-
webpack: newWebpackExport,
17+
const finalNextConfig = (
18+
phase: string,
19+
defaults: { defaultConfig: { [key: string]: unknown } },
20+
): NextConfigObject => {
21+
const materializedUserNextConfig =
22+
typeof userNextConfig === 'function' ? userNextConfig(phase, defaults) : userNextConfig;
23+
24+
return {
25+
...materializedUserNextConfig,
26+
// TODO When we add a way to disable the webpack plugin, doing so should turn this off, too
27+
productionBrowserSourceMaps: true,
28+
webpack: newWebpackExport,
29+
};
2230
};
2331

2432
return finalNextConfig;

packages/nextjs/src/config/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export { SentryCliPluginOptions as SentryWebpackPluginOptions } from '@sentry/we
44
* Overall Nextjs config
55
*/
66

7-
export type ExportedNextConfig = NextConfigObject;
7+
export type ExportedNextConfig = NextConfigObject | NextConfigFunction;
88

99
export type NextConfigObject = {
1010
// whether or not next should create source maps for browser code
@@ -17,6 +17,11 @@ export type NextConfigObject = {
1717
[key: string]: unknown;
1818
};
1919

20+
export type NextConfigFunction = (
21+
phase: string,
22+
defaults: { defaultConfig: { [key: string]: unknown } },
23+
) => NextConfigObject;
24+
2025
/**
2126
* Webpack config
2227
*/

packages/nextjs/test/config.test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ function materializeFinalNextConfig(
6262
userNextConfig: ExportedNextConfig,
6363
userSentryWebpackPluginConfig: SentryWebpackPluginOptions,
6464
): NextConfigObject {
65-
const finalConfigValues = withSentryConfig(userNextConfig, userSentryWebpackPluginConfig);
65+
const configFunction = withSentryConfig(userNextConfig, userSentryWebpackPluginConfig);
66+
const finalConfigValues = configFunction('phase-production-build', {
67+
defaultConfig: {},
68+
});
6669

6770
return finalConfigValues;
6871
}
@@ -128,6 +131,20 @@ describe('withSentryConfig', () => {
128131
}),
129132
);
130133
});
134+
135+
it("works when user's overall config is a function", () => {
136+
const userNextConfigFunction = () => userNextConfig;
137+
138+
const finalConfig = materializeFinalNextConfig(userNextConfigFunction, userSentryWebpackPluginConfig);
139+
140+
expect(finalConfig).toEqual(
141+
expect.objectContaining({
142+
...userNextConfigFunction(),
143+
productionBrowserSourceMaps: true,
144+
webpack: expect.any(Function), // `webpack` is tested specifically elsewhere
145+
}),
146+
);
147+
});
131148
});
132149

133150
describe('webpack config', () => {

0 commit comments

Comments
 (0)