Skip to content

Commit 299e18c

Browse files
committed
feat(tracing): Expose BrowserTracing in non-tracing bundles
In order to avoid breaking the bundler when a user opts out of tracing there.
1 parent 79d2903 commit 299e18c

File tree

10 files changed

+105
-22
lines changed

10 files changed

+105
-22
lines changed

packages/browser-integration-tests/suites/replay/replayShim/test.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ sentryTest(
3030
await forceFlushReplay();
3131

3232
expect(requestCount).toBe(0);
33-
expect(consoleMessages).toEqual([
34-
'You are using new Replay() even though this bundle does not include the replay integration.',
35-
]);
33+
expect(consoleMessages).toEqual(['You are using new Replay() even though this bundle does not include replay.']);
3634
},
3735
);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
dsn: 'https://[email protected]/1337',
7+
sampleRate: 1,
8+
integrations: [new Sentry.Integrations.BrowserTracing()],
9+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<body>
7+
<button onclick="console.log('Test log')">Click me</button>
8+
</body>
9+
</html>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { expect } from '@playwright/test';
2+
3+
import { sentryTest } from '../../../utils/fixtures';
4+
5+
sentryTest('exports a shim BrowserTracing integration for non-tracing bundles', async ({ getLocalTestPath, page }) => {
6+
const bundle = process.env.PW_BUNDLE;
7+
8+
if (!bundle || !bundle.startsWith('bundle_') || bundle.includes('tracing')) {
9+
sentryTest.skip();
10+
}
11+
12+
const consoleMessages: string[] = [];
13+
page.on('console', msg => consoleMessages.push(msg.text()));
14+
15+
let requestCount = 0;
16+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
17+
requestCount++;
18+
return route.fulfill({
19+
status: 200,
20+
contentType: 'application/json',
21+
body: JSON.stringify({ id: 'test-id' }),
22+
});
23+
});
24+
25+
const url = await getLocalTestPath({ testDir: __dirname });
26+
27+
await page.goto(url);
28+
29+
expect(requestCount).toBe(0);
30+
expect(consoleMessages).toEqual([
31+
'You are using new BrowserTracing() even though this bundle does not include tracing.',
32+
]);
33+
});

packages/browser/rollup.bundle.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const builds = [];
99
jsVersion,
1010
licenseTitle: '@sentry/browser',
1111
includeReplay: 'shim',
12+
includeBrowserTracing: 'shim',
1213
outputFileBase: () => `bundles/bundle${jsVersion === 'es5' ? '.es5' : ''}`,
1314
});
1415

@@ -23,6 +24,7 @@ const replayBaseBundleConfig = makeBaseBundleConfig({
2324
licenseTitle: '@sentry/browser & @sentry/replay',
2425
outputFileBase: () => 'bundles/bundle.replay',
2526
includeReplay: true,
27+
includeBrowserTracing: 'shim',
2628
});
2729

2830
builds.push(...makeBundleConfigVariants(replayBaseBundleConfig));
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import type { Integration } from '@sentry/types';
2+
3+
/**
4+
* This is a shim for the BrowserTracing integration.
5+
* It is needed in order for the CDN bundles to continue working when users add/remove tracing
6+
* from it, without changing their config. This is necessary for the loader mechanism.
7+
*/
8+
class BrowserTracingShim implements Integration {
9+
/**
10+
* @inheritDoc
11+
*/
12+
public static id: string = 'BrowserTracing';
13+
14+
/**
15+
* @inheritDoc
16+
*/
17+
public name: string = BrowserTracingShim.id;
18+
19+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
20+
public constructor(_options: any) {
21+
// eslint-disable-next-line no-console
22+
console.error('You are using new BrowserTracing() even though this bundle does not include tracing.');
23+
}
24+
25+
/** jsdoc */
26+
public setupOnce(): void {
27+
// noop
28+
}
29+
}
30+
31+
export { BrowserTracingShim as BrowserTracing };

packages/integration-shims/src/Replay.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class ReplayShim implements Integration {
1919
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2020
public constructor(_options: any) {
2121
// eslint-disable-next-line no-console
22-
console.error('You are using new Replay() even though this bundle does not include the replay integration.');
22+
console.error('You are using new Replay() even though this bundle does not include replay.');
2323
}
2424

2525
/** jsdoc */
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
export * from './Replay';
1+
export { Replay } from './Replay';
2+
export { BrowserTracing } from './BrowserTracing';

rollup/bundleHelpers.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
makeTSPlugin,
1919
makeExcludeBlockPlugin,
2020
makeSetSDKSourcePlugin,
21-
makeReplayShimPlugin,
21+
makeIntegrationShimPlugin,
2222
} from './plugins/index.js';
2323
import { mergePlugins } from './utils';
2424

@@ -45,11 +45,11 @@ export function makeBaseBundleConfig(options) {
4545
const licensePlugin = makeLicensePlugin(licenseTitle);
4646
const tsPlugin = makeTSPlugin(jsVersion.toLowerCase());
4747
const excludeReplayPlugin = makeExcludeBlockPlugin('REPLAY');
48-
const excludeReplayShimPlugin = makeExcludeBlockPlugin('REPLAY_SHIM');
4948
const excludeOfflineTransport = makeExcludeBlockPlugin('OFFLINE');
5049
const excludeBrowserProfiling = makeExcludeBlockPlugin('BROWSER_PROFILING');
5150
const excludeBrowserTracing = makeExcludeBlockPlugin('BROWSER_TRACING');
52-
const replayShimPlugin = makeReplayShimPlugin();
51+
const replayShimPlugin = makeIntegrationShimPlugin('@sentry/replay');
52+
const browserTracingShimPlugin = makeIntegrationShimPlugin('@sentry-internal/tracing');
5353

5454
// The `commonjs` plugin is the `esModuleInterop` of the bundling world. When used with `transformMixedEsModules`, it
5555
// will include all dependencies, imported or required, in the final bundle. (Without it, CJS modules aren't included
@@ -68,11 +68,7 @@ export function makeBaseBundleConfig(options) {
6868

6969
if (includeReplay === 'shim') {
7070
standAloneBundleConfig.plugins.push(replayShimPlugin);
71-
} else {
72-
standAloneBundleConfig.plugins.push(excludeReplayShimPlugin);
73-
}
74-
75-
if (!includeReplay) {
71+
} else if (!includeReplay) {
7672
standAloneBundleConfig.plugins.push(excludeReplayPlugin);
7773
}
7874

@@ -84,6 +80,9 @@ export function makeBaseBundleConfig(options) {
8480
standAloneBundleConfig.plugins.push(excludeBrowserProfiling);
8581
}
8682

83+
if (includeBrowserTracing === 'shim') {
84+
standAloneBundleConfig.plugins.push(browserTracingShimPlugin);
85+
}
8786
if (!includeBrowserTracing) {
8887
standAloneBundleConfig.plugins.push(excludeBrowserTracing);
8988
}

rollup/plugins/bundlePlugins.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,8 @@ export function makeTSPlugin(jsVersion) {
183183

184184
/**
185185
* Creates a Rollup plugin that removes all code between the `__ROLLUP_EXCLUDE_FROM_BUNDLES_BEGIN__`
186-
* and `__ROLLUP_EXCLUDE_FROM_BUNDLES_END__` comment guards. This is used to exclude the Replay integration
187-
* from the browser and browser+tracing bundles.
188-
* If we need to add more such guards in the future, we might want to refactor this into a more generic plugin.
186+
* and `__ROLLUP_EXCLUDE_FROM_BUNDLES_END__` comment guards.
187+
* This is used to exclude certain exports from variants of the browser bundle.
189188
*/
190189
export function makeExcludeBlockPlugin(type) {
191190
const replacementRegex = new RegExp(
@@ -197,8 +196,10 @@ export function makeExcludeBlockPlugin(type) {
197196

198197
const plugin = {
199198
transform(code, id) {
200-
const isBrowserIndexFile = path.resolve(id) === browserIndexFilePath;
201-
if (!isBrowserIndexFile || !replacementRegex.test(code)) {
199+
const resolvedPath = path.resolve(id);
200+
const shouldReplaceInFile = resolvedPath === browserIndexFilePath;
201+
202+
if (!shouldReplaceInFile || !replacementRegex.test(code)) {
202203
return null;
203204
}
204205

@@ -211,20 +212,20 @@ export function makeExcludeBlockPlugin(type) {
211212
},
212213
};
213214

214-
plugin.name = 'excludeReplay';
215+
plugin.name = 'excludeBlock';
215216

216217
return plugin;
217218
}
218219

219-
export function makeReplayShimPlugin() {
220+
export function makeIntegrationShimPlugin(originalImportName) {
220221
// This is designed to replace the re-export in browser/index.ts to export the shim
221222
const plugin = modify({
222-
find: '@sentry/replay',
223+
find: originalImportName,
223224
replace: '@sentry-internal/integration-shims',
224225
});
225226

226227
// give it a nicer name for later, when we'll need to sort the plugins
227-
plugin.name = 'replayShim';
228+
plugin.name = 'integrationShimPlugin';
228229

229230
return plugin;
230231
}

0 commit comments

Comments
 (0)