Skip to content

Commit 7f70aff

Browse files
feat: NextJS initialization config (#3285)
1 parent cbacaa9 commit 7f70aff

File tree

9 files changed

+192
-49
lines changed

9 files changed

+192
-49
lines changed

packages/nextjs/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717
"access": "public"
1818
},
1919
"dependencies": {
20-
"@sentry/browser": "6.2.0",
20+
"@sentry/core": "6.2.0",
21+
"@sentry/minimal": "6.2.0",
2122
"@sentry/node": "6.2.0",
22-
"@sentry/minimal": "6.2.0"
23+
"@sentry/react": "6.2.0"
2324
},
2425
"devDependencies": {
2526
"@sentry/types": "6.2.0",

packages/nextjs/src/browser.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1-
import { init as browserInit } from '@sentry/browser';
1+
import { init as reactInit } from '@sentry/react';
22

3-
import { MetadataBuilder, NextjsOptions } from './options';
3+
import { InitDecider } from './utils/initDecider';
4+
import { MetadataBuilder } from './utils/metadataBuilder';
5+
import { NextjsOptions } from './utils/nextjsOptions';
46

5-
/** Inits the Sentry NextJS SDK on the browser. */
7+
/** Inits the Sentry NextJS SDK on the browser with the React SDK. */
68
export function init(options: NextjsOptions): any {
7-
const metadataBuilder = new MetadataBuilder(options, ['nextjs', 'browser']);
9+
const metadataBuilder = new MetadataBuilder(options, ['nextjs', 'react']);
810
metadataBuilder.addSdkMetadata();
9-
browserInit(options);
11+
const initDecider = new InitDecider(options);
12+
if (initDecider.shouldInitSentry()) {
13+
reactInit(options);
14+
} else {
15+
// eslint-disable-next-line no-console
16+
console.log('[Sentry] Detected a non-production environment. Not initializing Sentry.');
17+
}
1018
}
1119

1220
export * from '@sentry/minimal';

packages/nextjs/src/node.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
import { init as nodeInit } from '@sentry/node';
22

3-
import { MetadataBuilder, NextjsOptions } from './options';
3+
import { InitDecider } from './utils/initDecider';
4+
import { MetadataBuilder } from './utils/metadataBuilder';
5+
import { NextjsOptions } from './utils/nextjsOptions';
46

57
/** Inits the Sentry NextJS SDK on node. */
68
export function init(options: NextjsOptions): any {
79
const metadataBuilder = new MetadataBuilder(options, ['nextjs', 'node']);
810
metadataBuilder.addSdkMetadata();
9-
nodeInit(options);
11+
const initDecider = new InitDecider(options);
12+
if (initDecider.shouldInitSentry()) {
13+
nodeInit(options);
14+
} else {
15+
// eslint-disable-next-line no-console
16+
console.log('[Sentry] Detected a non-production environment. Not initializing Sentry.');
17+
}
1018
}
1119

1220
export * from '@sentry/minimal';

packages/nextjs/src/sdk.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import { init as browserInit } from '@sentry/browser';
1+
import { init as reactInit } from '@sentry/react';
22

3-
import { MetadataBuilder, NextjsOptions } from './options';
3+
import { InitDecider } from './utils/initDecider';
4+
import { MetadataBuilder } from './utils/metadataBuilder';
5+
import { NextjsOptions } from './utils/nextjsOptions';
46

57
/**
68
* The Sentry NextJS SDK Client.
@@ -11,5 +13,11 @@ import { MetadataBuilder, NextjsOptions } from './options';
1113
export function init(options: NextjsOptions): void {
1214
const metadataBuilder = new MetadataBuilder(options, ['nextjs']);
1315
metadataBuilder.addSdkMetadata();
14-
browserInit(options);
16+
const initDecider = new InitDecider(options);
17+
if (initDecider.shouldInitSentry()) {
18+
reactInit(options);
19+
} else {
20+
// eslint-disable-next-line no-console
21+
console.log('[Sentry] Detected a non-production environment. Not initializing Sentry.');
22+
}
1523
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { NextjsOptions } from './nextjsOptions';
2+
3+
export class InitDecider {
4+
private _options: NextjsOptions;
5+
6+
constructor(options: NextjsOptions) {
7+
this._options = options;
8+
}
9+
10+
/**
11+
* Returns a boolean representing whether the NextJS SDK should be initialised.
12+
*
13+
* The SDK should be initialised if the `dev` option is set to true.
14+
* `dev` is optional, so if it isn't set or is set to false, the SDK will only
15+
* be initialised in a production environment.
16+
*/
17+
public shouldInitSentry(): boolean {
18+
if (this._isEnabledInDev() || this._isProdEnv()) {
19+
return true;
20+
}
21+
return false;
22+
}
23+
24+
/**
25+
* Returns true if the option `dev` is true, and false otherwise.
26+
*/
27+
private _isEnabledInDev(): boolean {
28+
return this._options.dev || false;
29+
}
30+
31+
/**
32+
* Returns whether the environment is a production environment.
33+
*/
34+
private _isProdEnv(): boolean {
35+
return process.env.NODE_ENV !== undefined && process.env.NODE_ENV === 'production';
36+
}
37+
}

packages/nextjs/src/options.ts renamed to packages/nextjs/src/utils/metadataBuilder.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
import { BrowserOptions, SDK_VERSION } from '@sentry/browser';
2-
import { NodeOptions } from '@sentry/node';
3-
import { Options, Package, SdkInfo } from '@sentry/types';
1+
import { SDK_VERSION } from '@sentry/core';
2+
import { Package, SdkInfo } from '@sentry/types';
3+
4+
import { NextjsOptions } from './nextjsOptions';
45

56
const SDK_NAME = 'sentry.javascript.nextjs';
67
const PACKAGE_NAME_PREFIX = 'npm:@sentry/';
78

8-
export interface NextjsOptions extends Options, BrowserOptions, NodeOptions {
9-
// TODO: options for NextJS
10-
}
11-
129
/**
1310
* A builder for the SDK metadata in the options for the SDK initialization.
1411
*/
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { NodeOptions } from '@sentry/node';
2+
import { BrowserOptions } from '@sentry/react';
3+
import { Options } from '@sentry/types';
4+
5+
export interface NextjsOptions extends Options, BrowserOptions, NodeOptions {
6+
/**
7+
* A flag enabling the initialization of the SDK in development and other
8+
* non-production environments. By default, the SDK is only initialised in
9+
* production.
10+
*/
11+
dev?: boolean;
12+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { InitDecider } from '../src/utils/initDecider';
2+
import { NextjsOptions } from '../src/utils/nextjsOptions';
3+
4+
function setDevEnv(): void {
5+
process.env.NODE_ENV = 'development';
6+
}
7+
8+
function setProdEnv(): void {
9+
process.env.NODE_ENV = 'production';
10+
}
11+
12+
function getEmptyOptions(): NextjsOptions {
13+
return {};
14+
}
15+
16+
function getDevTrueOptions(): NextjsOptions {
17+
return { dev: true };
18+
}
19+
20+
function getDevFalseOptions(): NextjsOptions {
21+
return { dev: false };
22+
}
23+
24+
describe('decide initialization in development', () => {
25+
beforeEach(setDevEnv);
26+
27+
test('without options', () => {
28+
const initDecider = new InitDecider(getEmptyOptions());
29+
expect(initDecider.shouldInitSentry()).toBeFalsy();
30+
});
31+
32+
test('without development', () => {
33+
const initDecider = new InitDecider(getDevFalseOptions());
34+
expect(initDecider.shouldInitSentry()).toBeFalsy();
35+
});
36+
37+
test('with development', () => {
38+
const initDecider = new InitDecider(getDevTrueOptions());
39+
expect(initDecider.shouldInitSentry()).toBeTruthy();
40+
});
41+
});
42+
43+
describe('decide initialization in production', () => {
44+
beforeEach(setProdEnv);
45+
46+
test('without options', () => {
47+
const initDecider = new InitDecider(getEmptyOptions());
48+
expect(initDecider.shouldInitSentry()).toBeTruthy();
49+
});
50+
51+
test('without development', () => {
52+
const initDecider = new InitDecider(getDevFalseOptions());
53+
expect(initDecider.shouldInitSentry()).toBeTruthy();
54+
});
55+
56+
test('with development', () => {
57+
const initDecider = new InitDecider(getDevTrueOptions());
58+
expect(initDecider.shouldInitSentry()).toBeTruthy();
59+
});
60+
});

yarn.lock

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3276,7 +3276,7 @@
32763276
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
32773277
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
32783278

3279-
"@sentry/browser@^6.2.0":
3279+
32803280
version "6.2.0"
32813281
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.2.0.tgz#4113a92bc82f55e63f30cb16a94f717bd0b95817"
32823282
integrity sha512-4r3paHcHXLemj471BtNDhUs2kvJxk5XDRplz1dbC/LHXN5PWEXP4anhGILxOlxqi4y33r53PIZu3xXFjznaVZA==
@@ -3306,7 +3306,7 @@
33063306
"@sentry/utils" "6.2.0"
33073307
tslib "^1.9.3"
33083308

3309-
"@sentry/[email protected]", "@sentry/minimal@^6.2.0":
3309+
33103310
version "6.2.0"
33113311
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.2.0.tgz#718b70babb55912eeb38babaf7823d1bcdd77d1e"
33123312
integrity sha512-haxsx8/ZafhZUaGeeMtY7bJt9HbDlqeiaXrRMp1CxGtd0ZRQwHt60imEjl6IH1I73SEWxNfqScGsX2s3HzztMg==
@@ -3315,7 +3315,7 @@
33153315
"@sentry/types" "6.2.0"
33163316
tslib "^1.9.3"
33173317

3318-
"@sentry/node@^6.2.0":
3318+
33193319
version "6.2.0"
33203320
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-6.2.0.tgz#4c1860822a4a73d24242e5254124bd3bf9028d52"
33213321
integrity sha512-02lXk+56tPA3lWTvNLMGorp77wUVti8wOs+TlYARkJ+N+16dwqEBSBTy3hCDxlxriB+qHchSIS+ovPGi6WNiYA==
@@ -3330,6 +3330,18 @@
33303330
lru_map "^0.3.3"
33313331
tslib "^1.9.3"
33323332

3333+
3334+
version "6.2.0"
3335+
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.2.0.tgz#bf46c38762554f246ca9dec527e6a5b3168fb0b0"
3336+
integrity sha512-Jf3s7om1iLpApkN26O7c3Ult3lS91ekZNC4WKtcPb6b+KOBQ36sB0d1KhL3hGZ55UKLmgZu3jn2hd7bJ9EY3yA==
3337+
dependencies:
3338+
"@sentry/browser" "6.2.0"
3339+
"@sentry/minimal" "6.2.0"
3340+
"@sentry/types" "6.2.0"
3341+
"@sentry/utils" "6.2.0"
3342+
hoist-non-react-statics "^3.3.2"
3343+
tslib "^1.9.3"
3344+
33333345
33343346
version "6.2.0"
33353347
resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.2.0.tgz#76c17e5dd3f1e61c8a4e3bd090f904a63d674765"
@@ -3341,7 +3353,7 @@
33413353
"@sentry/utils" "6.2.0"
33423354
tslib "^1.9.3"
33433355

3344-
"@sentry/[email protected]", "@sentry/types@^6.2.0":
3356+
33453357
version "6.2.0"
33463358
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.2.0.tgz#ca020ff42913c6b9f88a9d0c375b5ee3965a2590"
33473359
integrity sha512-vN4P/a+QqAuVfWFB9G3nQ7d6bgnM9jd/RLVi49owMuqvM24pv5mTQHUk2Hk4S3k7ConrHFl69E7xH6Dv5VpQnQ==
@@ -9967,25 +9979,26 @@ eslint-visitor-keys@^2.0.0:
99679979
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
99689980
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
99699981

9970-
eslint@7.6.0:
9971-
version "7.6.0"
9972-
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.6.0.tgz#522d67cfaea09724d96949c70e7a0550614d64d6"
9973-
integrity sha512-QlAManNtqr7sozWm5TF4wIH9gmUm2hE3vNRUvyoYAa4y1l5/jxD/PQStEjBMQtCqZmSep8UxrcecI60hOpe61w==
9982+
eslint@7.20.0:
9983+
version "7.20.0"
9984+
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.20.0.tgz#db07c4ca4eda2e2316e7aa57ac7fc91ec550bdc7"
9985+
integrity sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==
99749986
dependencies:
9975-
"@babel/code-frame" "^7.0.0"
9987+
"@babel/code-frame" "7.12.11"
9988+
"@eslint/eslintrc" "^0.3.0"
99769989
ajv "^6.10.0"
99779990
chalk "^4.0.0"
99789991
cross-spawn "^7.0.2"
99799992
debug "^4.0.1"
99809993
doctrine "^3.0.0"
99819994
enquirer "^2.3.5"
9982-
eslint-scope "^5.1.0"
9995+
eslint-scope "^5.1.1"
99839996
eslint-utils "^2.1.0"
9984-
eslint-visitor-keys "^1.3.0"
9985-
espree "^7.2.0"
9986-
esquery "^1.2.0"
9997+
eslint-visitor-keys "^2.0.0"
9998+
espree "^7.3.1"
9999+
esquery "^1.4.0"
998710000
esutils "^2.0.2"
9988-
file-entry-cache "^5.0.1"
10001+
file-entry-cache "^6.0.0"
998910002
functional-red-black-tree "^1.0.1"
999010003
glob-parent "^5.0.0"
999110004
globals "^12.1.0"
@@ -9996,7 +10009,7 @@ [email protected]:
999610009
js-yaml "^3.13.1"
999710010
json-stable-stringify-without-jsonify "^1.0.1"
999810011
levn "^0.4.1"
9999-
lodash "^4.17.19"
10012+
lodash "^4.17.20"
1000010013
minimatch "^3.0.4"
1000110014
natural-compare "^1.4.0"
1000210015
optionator "^0.9.1"
@@ -10005,30 +10018,29 @@ [email protected]:
1000510018
semver "^7.2.1"
1000610019
strip-ansi "^6.0.0"
1000710020
strip-json-comments "^3.1.0"
10008-
table "^5.2.3"
10021+
table "^6.0.4"
1000910022
text-table "^0.2.0"
1001010023
v8-compile-cache "^2.0.3"
1001110024

10012-
eslint@^7.20.0:
10013-
version "7.20.0"
10014-
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.20.0.tgz#db07c4ca4eda2e2316e7aa57ac7fc91ec550bdc7"
10015-
integrity sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==
10025+
eslint@7.6.0:
10026+
version "7.6.0"
10027+
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.6.0.tgz#522d67cfaea09724d96949c70e7a0550614d64d6"
10028+
integrity sha512-QlAManNtqr7sozWm5TF4wIH9gmUm2hE3vNRUvyoYAa4y1l5/jxD/PQStEjBMQtCqZmSep8UxrcecI60hOpe61w==
1001610029
dependencies:
10017-
"@babel/code-frame" "7.12.11"
10018-
"@eslint/eslintrc" "^0.3.0"
10030+
"@babel/code-frame" "^7.0.0"
1001910031
ajv "^6.10.0"
1002010032
chalk "^4.0.0"
1002110033
cross-spawn "^7.0.2"
1002210034
debug "^4.0.1"
1002310035
doctrine "^3.0.0"
1002410036
enquirer "^2.3.5"
10025-
eslint-scope "^5.1.1"
10037+
eslint-scope "^5.1.0"
1002610038
eslint-utils "^2.1.0"
10027-
eslint-visitor-keys "^2.0.0"
10028-
espree "^7.3.1"
10029-
esquery "^1.4.0"
10039+
eslint-visitor-keys "^1.3.0"
10040+
espree "^7.2.0"
10041+
esquery "^1.2.0"
1003010042
esutils "^2.0.2"
10031-
file-entry-cache "^6.0.0"
10043+
file-entry-cache "^5.0.1"
1003210044
functional-red-black-tree "^1.0.1"
1003310045
glob-parent "^5.0.0"
1003410046
globals "^12.1.0"
@@ -10039,7 +10051,7 @@ eslint@^7.20.0:
1003910051
js-yaml "^3.13.1"
1004010052
json-stable-stringify-without-jsonify "^1.0.1"
1004110053
levn "^0.4.1"
10042-
lodash "^4.17.20"
10054+
lodash "^4.17.19"
1004310055
minimatch "^3.0.4"
1004410056
natural-compare "^1.4.0"
1004510057
optionator "^0.9.1"
@@ -10048,7 +10060,7 @@ eslint@^7.20.0:
1004810060
semver "^7.2.1"
1004910061
strip-ansi "^6.0.0"
1005010062
strip-json-comments "^3.1.0"
10051-
table "^6.0.4"
10063+
table "^5.2.3"
1005210064
text-table "^0.2.0"
1005310065
v8-compile-cache "^2.0.3"
1005410066

@@ -17947,7 +17959,7 @@ rimraf@2, [email protected], rimraf@^2.2.8, rimraf@^2.3.4, rimraf@^2.4.3, rimraf@^2.4
1794717959
dependencies:
1794817960
glob "^7.1.3"
1794917961

17950-
rimraf@^3.0.0, rimraf@^3.0.1, rimraf@^3.0.2:
17962+
rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.1, rimraf@^3.0.2:
1795117963
version "3.0.2"
1795217964
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
1795317965
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==

0 commit comments

Comments
 (0)