Skip to content

Commit ab21117

Browse files
authored
fix(nextjs): Fix return type when injecting sentry code using webpack (#3625)
1 parent 800fc88 commit ab21117

File tree

1 file changed

+11
-9
lines changed

1 file changed

+11
-9
lines changed

packages/nextjs/src/utils/config.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ const _injectFile = (entryProperty: EntryPropertyObject, injectionPoint: string,
7777
entryProperty[injectionPoint] = injectedInto;
7878
};
7979

80-
const injectSentry = async (origEntryProperty: EntryProperty, isServer: boolean): Promise<EntryProperty> => {
80+
const injectSentry = async (origEntryProperty: EntryProperty, isServer: boolean): Promise<EntryPropertyObject> => {
8181
// The `entry` entry in a webpack config can be a string, array of strings, object, or function. By default, nextjs
8282
// sets it to an async function which returns the promise of an object of string arrays. Because we don't know whether
8383
// someone else has come along before us and changed that, we need to check a few things along the way. The one thing
@@ -106,11 +106,7 @@ const injectSentry = async (origEntryProperty: EntryProperty, isServer: boolean)
106106
else {
107107
_injectFile(newEntryProperty, 'main', SENTRY_CLIENT_CONFIG_FILE);
108108
}
109-
// TODO: hack made necessary because the async-ness of this function turns our object back into a promise, meaning the
110-
// internal `next` code which should do this doesn't
111-
if ('main.js' in newEntryProperty) {
112-
delete newEntryProperty['main.js'];
113-
}
109+
114110
return newEntryProperty;
115111
};
116112

@@ -178,9 +174,15 @@ export function withSentryConfig(
178174
newConfig.devtool = 'source-map';
179175
}
180176

181-
// Inject user config files (`sentry.client.confg.js` and `sentry.server.config.js`), which is where `Sentry.init()`
182-
// is called. By adding them here, we ensure that they're bundled by webpack as part of both server code and client code.
183-
newConfig.entry = (injectSentry(newConfig.entry, options.isServer) as unknown) as EntryProperty;
177+
// Tell webpack to inject user config files (containing the two `Sentry.init()` calls) into the appropriate output
178+
// bundles. Store a separate reference to the original `entry` value to avoid an infinite loop. (In a synchronous
179+
// world, `x = () => f(x)` is fine, because the dereferencing is guaranteed to happen before the assignment, meaning
180+
// we know f will get the original value of x. But in an async world, if we do `x = async () => f(x)`, the
181+
// assignment happens *before* the dereferencing, meaning f is passed the new value. In other words, in that
182+
// scenario, the new value is defined in terms of itself, with predictably bad consequences. Theoretically this
183+
// could also be fixed by using `bind`, but this is way simpler.)
184+
const origEntryProperty = newConfig.entry;
185+
newConfig.entry = () => injectSentry(origEntryProperty, options.isServer);
184186

185187
// Add the Sentry plugin, which uploads source maps to Sentry when not in dev
186188
newConfig.plugins.push(

0 commit comments

Comments
 (0)