Skip to content

Commit d5b335d

Browse files
fix: Add tslib dependecy for next.js + fixes (#3487)
* fix: Add tslib dependecy * fix: Add safeguard * fix: Inject client after entry in frontend * Update packages/nextjs/src/utils/config.ts Co-authored-by: iker barriocanal <[email protected]> * ref: CR * meta: Changelog Co-authored-by: iker barriocanal <[email protected]>
1 parent 6874655 commit d5b335d

File tree

3 files changed

+43
-24
lines changed

3 files changed

+43
-24
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott
66

7+
## 6.3.5
8+
9+
- [nextjs] fix: Add tslib dependecy; change inject order (#3487)
10+
711
## 6.3.4
812

913
- [nextjs] fix: API routes logging (#3479)

packages/nextjs/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"@sentry/node": "6.3.4",
2323
"@sentry/react": "6.3.4",
2424
"@sentry/utils": "6.3.4",
25-
"@sentry/webpack-plugin": "1.15.0"
25+
"@sentry/webpack-plugin": "1.15.0",
26+
"tslib": "^1.9.3"
2627
},
2728
"devDependencies": {
2829
"@sentry/types": "6.3.4",

packages/nextjs/src/utils/config.ts

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,36 +26,50 @@ type EntryProperty = (() => Promise<EntryPropertyObject>) | EntryPropertyObject;
2626
type EntryPropertyObject = PlainObject<string | Array<string> | EntryPointObject>;
2727
type EntryPointObject = { import: string | Array<string> };
2828

29+
const sentryClientConfig = './sentry.client.config.js';
30+
const sentryServerConfig = './sentry.server.config.js';
31+
2932
/** Add a file (`injectee`) to a given element (`injectionPoint`) of the `entry` property */
3033
const _injectFile = (entryProperty: EntryPropertyObject, injectionPoint: string, injectee: string): void => {
3134
// can be a string, array of strings, or object whose `import` property is one of those two
3235
let injectedInto = entryProperty[injectionPoint];
33-
// whatever the format, add in the sentry file
34-
injectedInto =
35-
typeof injectedInto === 'string'
36-
? // string case
37-
[injectee, injectedInto]
38-
: // not a string, must be an array or object
39-
Array.isArray(injectedInto)
40-
? // array case
41-
[injectee, ...injectedInto]
42-
: // object case
43-
{
44-
...injectedInto,
45-
import:
46-
typeof injectedInto.import === 'string'
47-
? // string case for inner property
48-
[injectee, injectedInto.import]
49-
: // array case for inner property
50-
[injectee, ...injectedInto.import],
51-
};
36+
37+
// Sometimes especially for older next.js versions it happens we don't have an entry point
38+
if (!injectedInto) {
39+
// eslint-disable-next-line no-console
40+
console.error(`[Sentry] Can't inject ${injectee}, no entrypoint is defined.`);
41+
return;
42+
}
43+
44+
// In case we inject our client config, we need to add it after the frontend code
45+
// otherwise the runtime config isn't loaded. See: https://github.com/getsentry/sentry-javascript/issues/3485
46+
const isClient = injectee === sentryClientConfig;
47+
48+
if (typeof injectedInto === 'string') {
49+
injectedInto = isClient ? [injectedInto, injectee] : [injectee, injectedInto];
50+
} else if (Array.isArray(injectedInto)) {
51+
injectedInto = isClient ? [...injectedInto, injectee] : [injectee, ...injectedInto];
52+
} else {
53+
let importVal: string | string[] | EntryPointObject;
54+
if (typeof injectedInto.import === 'string') {
55+
importVal = isClient ? [injectedInto.import, injectee] : [injectee, injectedInto.import];
56+
} else {
57+
// If it's not a string, the inner value is an array
58+
importVal = isClient ? [...injectedInto.import, injectee] : [injectee, ...injectedInto.import];
59+
}
60+
61+
injectedInto = {
62+
...injectedInto,
63+
import: importVal,
64+
};
65+
}
66+
5267
entryProperty[injectionPoint] = injectedInto;
5368
};
5469

5570
const injectSentry = async (origEntryProperty: EntryProperty, isServer: boolean): Promise<EntryProperty> => {
5671
// 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.
72+
// object has string arrays for values.
5973
// The `entry` entry in a webpack config can be a string, array of strings, object, or function. By default, nextjs
6074
// sets it to an async function which returns the promise of an object of string arrays. Because we don't know whether
6175
// someone else has come along before us and changed that, we need to check a few things along the way. The one thing
@@ -72,13 +86,13 @@ const injectSentry = async (origEntryProperty: EntryProperty, isServer: boolean)
7286
Object.keys(newEntryProperty).forEach(key => {
7387
if (key === 'pages/_document' || key.includes('pages/api')) {
7488
// 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');
89+
_injectFile(newEntryProperty as EntryPropertyObject, key, sentryServerConfig);
7690
}
7791
});
7892
}
7993
// On the client, it's sufficient to inject it into the `main` JS code, which is included in every browser page.
8094
else {
81-
_injectFile(newEntryProperty, 'main', './sentry.client.config.js');
95+
_injectFile(newEntryProperty, 'main', sentryClientConfig);
8296
}
8397
// TODO: hack made necessary because the async-ness of this function turns our object back into a promise, meaning the
8498
// internal `next` code which should do this doesn't

0 commit comments

Comments
 (0)