@@ -15,8 +15,7 @@ type WebpackExport = (config: WebpackConfig, options: WebpackOptions) => Webpack
15
15
16
16
// The two arguments passed to the exported `webpack` function, as well as the thing it returns
17
17
type WebpackConfig = { devtool : string ; plugins : PlainObject [ ] ; entry : EntryProperty } ;
18
- // TODO use real webpack types
19
- type WebpackOptions = { dev : boolean ; isServer : boolean } ;
18
+ type WebpackOptions = { dev : boolean ; isServer : boolean ; buildId : string } ;
20
19
21
20
// For our purposes, the value for `entry` is either an object, or a function which returns such an object
22
21
type EntryProperty = ( ( ) => Promise < EntryPropertyObject > ) | EntryPropertyObject ;
@@ -27,33 +26,10 @@ type EntryProperty = (() => Promise<EntryPropertyObject>) | EntryPropertyObject;
27
26
type EntryPropertyObject = PlainObject < string | Array < string > | EntryPointObject > ;
28
27
type EntryPointObject = { import : string | Array < string > } ;
29
28
30
- const injectSentry = async ( origEntryProperty : EntryProperty , isServer : boolean ) : Promise < EntryProperty > => {
31
- // Out of the box, nextjs uses the `() => Promise<EntryPropertyObject>)` flavor of EntryProperty, where the returned
32
- // object has string arrays for values. But because we don't know whether someone else has come along before us and
33
- // changed that, we need to check a few things along the way.
34
-
35
- // The `entry` entry in a webpack config can be a string, array of strings, object, or function. By default, nextjs
36
- // sets it to an async function which returns the promise of an object of string arrays. Because we don't know whether
37
- // someone else has come along before us and changed that, we need to check a few things along the way. The one thing
38
- // we know is that it won't have gotten *simpler* in form, so we only need to worry about the object and function
39
- // options. See https://webpack.js.org/configuration/entry-context/#entry.
40
-
41
- let newEntryProperty = origEntryProperty ;
42
-
43
- if ( typeof origEntryProperty === 'function' ) {
44
- newEntryProperty = await origEntryProperty ( ) ;
45
- }
46
-
47
- newEntryProperty = newEntryProperty as EntryPropertyObject ;
48
-
49
- // according to vercel, we only need to inject Sentry in one spot for server and one spot for client, and because
50
- // those are used as bases, it will apply everywhere
51
- const injectionPoint = isServer ? 'pages/_document' : 'main' ;
52
- const injectee = isServer ? './sentry.server.config.js' : './sentry.client.config.js' ;
53
-
29
+ /** Add a file (`injectee`) to a given element (`injectionPoint`) of the `entry` property */
30
+ const _injectFile = ( entryProperty : EntryPropertyObject , injectionPoint : string , injectee : string ) : void => {
54
31
// can be a string, array of strings, or object whose `import` property is one of those two
55
- let injectedInto = newEntryProperty [ injectionPoint ] ;
56
-
32
+ let injectedInto = entryProperty [ injectionPoint ] ;
57
33
// whatever the format, add in the sentry file
58
34
injectedInto =
59
35
typeof injectedInto === 'string'
@@ -73,15 +49,42 @@ const injectSentry = async (origEntryProperty: EntryProperty, isServer: boolean)
73
49
: // array case for inner property
74
50
[ injectee , ...injectedInto . import ] ,
75
51
} ;
52
+ entryProperty [ injectionPoint ] = injectedInto ;
53
+ } ;
76
54
77
- newEntryProperty [ injectionPoint ] = injectedInto ;
78
-
55
+ const injectSentry = async ( origEntryProperty : EntryProperty , isServer : boolean ) : Promise < EntryProperty > => {
56
+ // Out of the box, nextjs uses the `() => Promise<EntryPropertyObject>)` flavor of EntryProperty, where the returned
57
+ // object has string arrays for values. But because we don't know whether someone else has come along before us and
58
+ // changed that, we need to check a few things along the way.
59
+ // The `entry` entry in a webpack config can be a string, array of strings, object, or function. By default, nextjs
60
+ // sets it to an async function which returns the promise of an object of string arrays. Because we don't know whether
61
+ // someone else has come along before us and changed that, we need to check a few things along the way. The one thing
62
+ // we know is that it won't have gotten *simpler* in form, so we only need to worry about the object and function
63
+ // options. See https://webpack.js.org/configuration/entry-context/#entry.
64
+ let newEntryProperty = origEntryProperty ;
65
+ if ( typeof origEntryProperty === 'function' ) {
66
+ newEntryProperty = await origEntryProperty ( ) ;
67
+ }
68
+ newEntryProperty = newEntryProperty as EntryPropertyObject ;
69
+ // On the server, we need to inject the SDK into both into the base page (`_document`) and into individual API routes
70
+ // (which have no common base).
71
+ if ( isServer ) {
72
+ Object . keys ( newEntryProperty ) . forEach ( key => {
73
+ if ( key === 'pages/_document' || key . includes ( 'pages/api' ) ) {
74
+ // for some reason, because we're now in a function, we have to cast again
75
+ _injectFile ( newEntryProperty as EntryPropertyObject , key , './sentry.server.config.js' ) ;
76
+ }
77
+ } ) ;
78
+ }
79
+ // On the client, it's sufficient to inject it into the `main` JS code, which is included in every browser page.
80
+ else {
81
+ _injectFile ( newEntryProperty , 'main' , './sentry.client.config.js' ) ;
82
+ }
79
83
// TODO: hack made necessary because the async-ness of this function turns our object back into a promise, meaning the
80
84
// internal `next` code which should do this doesn't
81
85
if ( 'main.js' in newEntryProperty ) {
82
86
delete newEntryProperty [ 'main.js' ] ;
83
87
}
84
-
85
88
return newEntryProperty ;
86
89
} ;
87
90
@@ -97,7 +100,6 @@ export function withSentryConfig(
97
100
providedWebpackPluginOptions : Partial < SentryCliPluginOptions > = { } ,
98
101
) : NextConfigExports {
99
102
const defaultWebpackPluginOptions = {
100
- release : getSentryRelease ( ) ,
101
103
url : process . env . SENTRY_URL ,
102
104
org : process . env . SENTRY_ORG ,
103
105
project : process . env . SENTRY_PROJECT ,
@@ -144,6 +146,7 @@ export function withSentryConfig(
144
146
// TODO it's not clear how to do this better, but there *must* be a better way
145
147
new ( ( SentryWebpackPlugin as unknown ) as typeof defaultWebpackPlugin ) ( {
146
148
dryRun : options . dev ,
149
+ release : getSentryRelease ( options . buildId ) ,
147
150
...defaultWebpackPluginOptions ,
148
151
...providedWebpackPluginOptions ,
149
152
} ) ,
0 commit comments