Skip to content

Commit 415d04e

Browse files
committed
Merge branch 'master' into kmclb-next-js-performance
2 parents 4c2a385 + 3c0d44e commit 415d04e

File tree

7 files changed

+120
-113
lines changed

7 files changed

+120
-113
lines changed

.github/workflows/build.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ jobs:
7676
# this file) to a constant and skip rebuilding all of the packages each time CI runs.
7777
if: steps.cache_built_packages.outputs.cache-hit == ''
7878
run: yarn build
79+
# We are performing a `prepublishOnly` step manually because build workflow is not responsible for publishing
80+
# the actual release. It only creates artifacts which then are uploaded and used by another workflow.
81+
# Because of that, any `prepublishOnly` script is skipped and files it produces are not included in the tarball.
82+
# We also cannot use `prepare` script which would be more suited, because it's run only before `pack` is called,
83+
# and it's done from a `release` workflow and not here.
84+
- name: Run prepublishOnly script
85+
if: startsWith(github.ref, 'refs/heads/release/')
86+
run: yarn prepublishOnly
7987
outputs:
8088
# this needs to be passed on, because the `needs` context only looks at direct ancestors (so steps which depend on
8189
# `job_build` can't see `job_install_deps` and what it returned)

packages/browser/src/loader.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
// come out in the wrong order. Because of that we don't need async=1 as GA does.
5959
// it was probably(?) a legacy behavior that they left to not modify few years old snippet
6060
// https://www.html5rocks.com/en/tutorials/speed/script-loading/
61-
var _currentScriptTag = _document.getElementsByTagName(_script)[0];
61+
var _currentScriptTag = _document.scripts[0];
6262
var _newScriptTag = _document.createElement(_script);
6363
_newScriptTag.src = _sdkBundleUrl;
6464
_newScriptTag.setAttribute('crossorigin', 'anonymous');

packages/nextjs/src/index.server.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import { RewriteFrames } from '@sentry/integrations';
12
import { configureScope, init as nodeInit } from '@sentry/node';
23

34
import { instrumentServer } from './utils/instrumentServer';
45
import { MetadataBuilder } from './utils/metadataBuilder';
56
import { NextjsOptions } from './utils/nextjsOptions';
6-
import { defaultRewriteFrames, getFinalServerIntegrations } from './utils/serverIntegrations';
7+
import { addIntegration } from './utils/userIntegrations';
78

89
export * from '@sentry/node';
910

@@ -16,12 +17,7 @@ export function init(options: NextjsOptions): void {
1617
const metadataBuilder = new MetadataBuilder(options, ['nextjs', 'node']);
1718
metadataBuilder.addSdkMetadata();
1819
options.environment = options.environment || process.env.NODE_ENV;
19-
if (options.integrations) {
20-
options.integrations = getFinalServerIntegrations(options.integrations);
21-
} else {
22-
options.integrations = [defaultRewriteFrames];
23-
}
24-
20+
addServerIntegrations(options);
2521
// Right now we only capture frontend sessions for Next.js
2622
options.autoSessionTracking = false;
2723

@@ -31,6 +27,23 @@ export function init(options: NextjsOptions): void {
3127
});
3228
}
3329

30+
const SOURCEMAP_FILENAME_REGEX = /^.*\/\.next\//;
31+
32+
const defaultRewriteFramesIntegration = new RewriteFrames({
33+
iteratee: frame => {
34+
frame.filename = frame.filename?.replace(SOURCEMAP_FILENAME_REGEX, 'app:///_next/');
35+
return frame;
36+
},
37+
});
38+
39+
function addServerIntegrations(options: NextjsOptions): void {
40+
if (options.integrations) {
41+
options.integrations = addIntegration(defaultRewriteFramesIntegration, options.integrations);
42+
} else {
43+
options.integrations = [defaultRewriteFramesIntegration];
44+
}
45+
}
46+
3447
export { withSentryConfig } from './utils/config';
3548
export { withSentry } from './utils/handlers';
3649

packages/nextjs/src/utils/serverIntegrations.ts

Lines changed: 0 additions & 55 deletions
This file was deleted.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { Integration } from '@sentry/types';
2+
3+
export type UserFunctionIntegrations = (integrations: Integration[]) => Integration[];
4+
type UserIntegrations = Integration[] | UserFunctionIntegrations;
5+
6+
/**
7+
* Retrieves the patched integrations with the provided integration.
8+
*
9+
* The integration must be present in the final user integrations, and they are compared
10+
* by integration name. If the user has defined one, there's nothing to patch; if not,
11+
* the provided integration is added.
12+
*
13+
* @param integration The integration to patch, if necessary.
14+
* @param userIntegrations Integrations defined by the user.
15+
* @returns Final integrations, patched if necessary.
16+
*/
17+
export function addIntegration(integration: Integration, userIntegrations: UserIntegrations): UserIntegrations {
18+
if (Array.isArray(userIntegrations)) {
19+
return addIntegrationToArray(integration, userIntegrations);
20+
} else {
21+
return addIntegrationToFunction(integration, userIntegrations);
22+
}
23+
}
24+
25+
function addIntegrationToArray(integration: Integration, userIntegrations: Integration[]): Integration[] {
26+
if (userIntegrations.map(int => int.name).includes(integration.name)) {
27+
return userIntegrations;
28+
}
29+
return [...userIntegrations, integration];
30+
}
31+
32+
function addIntegrationToFunction(
33+
integration: Integration,
34+
userIntegrationsFunc: UserFunctionIntegrations,
35+
): UserFunctionIntegrations {
36+
const wrapper: UserFunctionIntegrations = defaultIntegrations => {
37+
const userFinalIntegrations = userIntegrationsFunc(defaultIntegrations);
38+
return addIntegrationToArray(integration, userFinalIntegrations);
39+
};
40+
return wrapper;
41+
}

packages/nextjs/test/serverIntegrations.test.ts

Lines changed: 0 additions & 50 deletions
This file was deleted.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { RewriteFrames } from '@sentry/integrations';
2+
import { Integration } from '@sentry/types';
3+
4+
import { addIntegration, UserFunctionIntegrations } from '../src/utils/userIntegrations';
5+
6+
const testIntegration = new RewriteFrames();
7+
8+
describe('user integrations without any integrations', () => {
9+
test('as an array', () => {
10+
const userIntegrations: Integration[] = [];
11+
// Should get a single integration
12+
let finalIntegrations = addIntegration(testIntegration, userIntegrations);
13+
expect(finalIntegrations).toBeInstanceOf(Array);
14+
finalIntegrations = finalIntegrations as Integration[];
15+
expect(finalIntegrations).toHaveLength(1);
16+
expect(finalIntegrations[0]).toMatchObject(testIntegration);
17+
});
18+
19+
test('as a function', () => {
20+
const userIntegrationFnc: UserFunctionIntegrations = (): Integration[] => [];
21+
// Should get a single integration
22+
const integrationWrapper = addIntegration(testIntegration, userIntegrationFnc);
23+
expect(integrationWrapper).toBeInstanceOf(Function);
24+
const finalIntegrations = (integrationWrapper as UserFunctionIntegrations)([]);
25+
expect(finalIntegrations).toHaveLength(1);
26+
expect(finalIntegrations[0]).toMatchObject(testIntegration);
27+
});
28+
});
29+
30+
describe('user integrations with integrations', () => {
31+
test('as an array', () => {
32+
const userIntegrations = [new RewriteFrames()];
33+
// Should get the same array (with no patches)
34+
const finalIntegrations = addIntegration(testIntegration, userIntegrations);
35+
expect(finalIntegrations).toMatchObject(userIntegrations);
36+
});
37+
38+
test('as a function', () => {
39+
const userIntegrations = [new RewriteFrames()];
40+
const integrationsFnc: UserFunctionIntegrations = (_integrations: Integration[]): Integration[] => {
41+
return userIntegrations;
42+
};
43+
// Should get a function that returns the test integration
44+
let finalIntegrations = addIntegration(testIntegration, integrationsFnc);
45+
expect(typeof finalIntegrations === 'function').toBe(true);
46+
expect(finalIntegrations).toBeInstanceOf(Function);
47+
finalIntegrations = finalIntegrations as UserFunctionIntegrations;
48+
expect(finalIntegrations([])).toMatchObject(userIntegrations);
49+
});
50+
});

0 commit comments

Comments
 (0)