Skip to content

Commit bfd6795

Browse files
committed
feat(js): Update web worker guide with new webWorkerIntegration APIs
1 parent 0f4cb5b commit bfd6795

File tree

3 files changed

+162
-42
lines changed

3 files changed

+162
-42
lines changed

docs/platforms/javascript/common/best-practices/web-workers.mdx

Lines changed: 109 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,9 @@ sidebar_order: 9000
66
supported:
77
- javascript
88
notSupported:
9-
- javascript.angular
109
- javascript.cordova
1110
- javascript.electron
12-
- javascript.ember
1311
- javascript.gatsby
14-
- javascript.nextjs
15-
- javascript.nuxt
16-
- javascript.react
17-
- javascript.solid
18-
- javascript.solidstart
19-
- javascript.vue
20-
- javascript.wasm
2112
- javascript.node
2213
- javascript.aws-lambda
2314
- javascript.azure-functions
@@ -29,28 +20,19 @@ notSupported:
2920
- javascript.hono
3021
- javascript.koa
3122
- javascript.nestjs
32-
- javascript.tanstackstart-react
3323
---
3424

35-
Sentry's Browser SDK supports [Web Workers API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API). To capture unhandled errors from Web Workers:
25+
Sentry's Browser SDK supports the [Web Workers API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API).
26+
You can use the SDK in different ways, though we recommend initializing it in the main thread to capture unhandled errors from workers automatically.
3627

37-
Install `@sentry/browser` using your package manager:
28+
## Recommended Setup
3829

39-
```bash {tabTitle:npm}
40-
npm install @sentry/browser --save
41-
```
42-
43-
```bash {tabTitle:yarn}
44-
yarn add @sentry/browser
45-
```
30+
_Available since_ : 9.40.0
4631

47-
```bash {tabTitle:pnpm}
48-
pnpm add @sentry/browser
49-
```
50-
51-
Then you can use it:
32+
To capture unhandled errors from Web Workers, initialize Sentry in your application code that runs on the main thread
33+
and let the SDK know about the web worker:
5234

53-
```javascript {filename:index.js}
35+
```javascript {filename:index.js} {1-5,9-10}
5436
import * as Sentry from "@sentry/browser";
5537

5638
Sentry.init({
@@ -59,34 +41,75 @@ Sentry.init({
5941

6042
const worker = new Worker("worker.js");
6143

44+
// Add the integration before listening to worker messages
45+
Sentry.addIntegration(Sentry.webWorkerIntegration({ worker }));
46+
47+
worker.onmessage = (event) => {
48+
// ...
49+
}
50+
```
51+
52+
Then, establish communication between the worker and the SDK:
53+
54+
```javascript {filename:worker.js}{1-4}
55+
import * as Sentry from "@sentry/browser";
56+
57+
// Call this before posting any message
58+
Sentry.registerWorker({ self })
59+
6260
// Errors from `onmessage` callback of `worker.js`
63-
// will be captured.
64-
worker.postMessage("Hello!");
61+
// will be captured automatically.
62+
self.postMessage("Worker ready!");
63+
self.onmessage = (event) => {
64+
// ...
65+
}
6566
```
6667

67-
<Alert level="warning" title="Manual Capturing">
68+
<Alert level="warning" title="The Order Matters">
6869

69-
To capture errors or messages manually, such as to use `captureMessage` or `captureException` inside Web Workers, Sentry should be initialized inside each Web Workers' own scope. Only unhandled errors will be captured and sent to Sentry without worker-level initialization.
70+
Ensure that in both, your main thread code as well as the worker, you set up Sentry before you start listening to messages.
71+
The Sentry SDK sends messages from the worker to the main thread, so if you start listening before Sentry is initialized,
72+
the messages will appear in your listeners and you have to handle them manually.
7073

7174
</Alert>
7275

73-
#### Usage Without Worker-Level Initialization
76+
### Multiple Workers
77+
78+
The `sentryWebWorkerIntegration` supports registering multiple workers.
79+
You can add them directly, when you initialize the integration, or later on.
80+
This is helpful, if you have workers that are initialized at different points in time in your application lifecycle.
7481

75-
```javascript {filename:worker.js}
82+
```javascript {filename:index.js} {1-5, 10-14, 18}
7683
import * as Sentry from "@sentry/browser";
7784

78-
self.onmessage = (message) => {
79-
// This will fail silently.
80-
Sentry.captureMessage("Message received");
85+
Sentry.init({
86+
dsn: "___PUBLIC_DSN___",
87+
});
8188

82-
// This error will be captured.
83-
throw new Error();
84-
};
89+
const worker1 = new Worker("worker.js");
90+
const worker2 = new Worker("worker2.js");
91+
92+
// Multiple workers can be added directly:
93+
const webWorkerIntegration = Sentry.webWorkerIntegration({ worker: [worker1, worker2] });
94+
Sentry.addIntegration(webWorkerIntegration);
95+
96+
// or later on:
97+
const worker3 = new Worker("worker3.js");
98+
webWorkerIntegration.addWorker(worker3);
8599
```
86100

87-
#### Usage With Worker-Level Initialization
101+
<Alert level="warning" title="Keep in Mind">
102+
103+
- Every worker must call `Sentry.registerWorker({ self })` to register itself with the SDK.
104+
- Do not call `Sentry.webWorkerIntegration()` multiple times! This will lead to unexpected behavior.
105+
106+
</Alert>
107+
108+
## Manually Capturing Errors
88109

89-
```javascript {filename:worker.js}
110+
To capture errors or messages manually, via `Sentry.captureMessage` or `Sentry.captureException` inside Web Workers, you can also import the SDK in the worker and initialize it.
111+
112+
```javascript {filename:worker.js} {1-5,9}
90113
import * as Sentry from "@sentry/browser";
91114

92115
Sentry.init({
@@ -102,10 +125,54 @@ self.onmessage = (message) => {
102125
};
103126
```
104127

128+
Note that initializing the SDK in the worker **completely decouples** it from the SDK running on the main thread.
129+
This means that data like user, tags, traces or scope data set on either side will not be shared with the other side.
130+
131+
Sometimes, this is the better approach, for instance if you develop a worker that is used in arbitrary applications.
132+
Other times, if the worker is just part of your application, you likely want to use the [SDK from the main thread](#recommended-setup).
133+
134+
<Alert level="warning" title="Keep in Mind">
135+
136+
If you initialize the SDK in the worker, don't use the `Sentry.webWorkerIntegration` to register the worker.
137+
Likewise, don't use the `Sentry.registerWorker` in the worker. Both methods are only supposed to be used when relying on the SDK [from the main thread](#recommended-setup).
138+
139+
</Alert>
140+
105141
### Integrations
106142

107-
Note, that if you use non-default integrations inside web workers, they may not function as expected. But non-default integrations that are enabled outside of a worker’s scope won’t be affected and will function as expected. This includes Session Replay.
143+
Note, that if you use non-default integrations inside web workers, they may not function as expected.
144+
However, non-default integrations that are enabled on the main thread SDK, won't be affected and will work as expected.
145+
This includes Session Replay.
146+
147+
## Source Maps
148+
149+
To ensure that errors from web workers are properly mapped to their original source code, you need to provide source maps to Sentry.
150+
You likely already provide source maps to Sentry for your main application code, but you might need to make adjustments for your worker.
151+
152+
Importantly, ensure that your bundler also **emits source maps** for the worker bundle(s).
108153

109-
### Source Maps
154+
### Vite
155+
If you use Vite to build your worker, note that the worker build does not take the same plugin as the main code build.
156+
Therefore, you need to add Sentry's Vite plugin to the worker build, in addition to the top-level `plugins` array:
110157

111-
Sentry's source maps integration is supported inside Web Workers, if provided. Learn more about providing your [source maps](/platforms/javascript/sourcemaps/) to Sentry.
158+
```javascript {filename:vite.config.mjs}{1-4,8-9,13,16-17}
159+
const sentryPlugin = sentryVitePlugin({
160+
org: "sentry-sdks",
161+
project: "javascript",
162+
});
163+
164+
export default defineConfig({
165+
build: {
166+
// This enables source maps for main and worker bundles
167+
sourcemap: "hidden",
168+
},
169+
170+
// Vite plugin for main bundle
171+
plugins: [sentryPlugin],
172+
173+
worker: {
174+
// Vite plugin for worker bundle
175+
plugins: () => [...sentryPlugin],
176+
},
177+
});
178+
```
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
title: WebWorker
3+
description: "Adds source code from inline JavaScript of the current page's HTML."
4+
notSupported:
5+
- javascript.cordova
6+
- javascript.node
7+
- javascript.aws-lambda
8+
- javascript.azure-functions
9+
- javascript.connect
10+
- javascript.express
11+
- javascript.fastify
12+
- javascript.gcp-functions
13+
- javascript.hapi
14+
- javascript.hono
15+
- javascript.koa
16+
- javascript.nestjs
17+
- javascript.deno
18+
- javascript.cloudflare
19+
- javascript.bun
20+
---
21+
22+
_Import name: `Sentry.webWorkerIntegration`_
23+
24+
This integration, together with `Sentry.registerWorker()`, establishes communication between the browser's main thread and one or multiple [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API)s.
25+
It listens to worker messages from the passed workers and forwards them to the main thread.
26+
27+
Read our <PlatformLink to="/best-practices/web-workers/">Web Worker Guide</PlatformLink> for more information.
28+
29+
<Expandable title="What does this integration do?">
30+
31+
This integration listens to a message, sent from the worker when it calls `Sentry.registerWorker({ self })`.
32+
The purpose is to sync source map information (debugIds) between the main thread and the worker so that worker
33+
errors caught by the main thread SDK are properly mapped to the worker's source code.
34+
35+
</Expandable>
36+
37+
38+
## Options
39+
40+
### `worker`
41+
42+
_Type: `Worker | Array<Worker>`_
43+
44+
The web worker(s) to listen to. Every worker must call `Sentry.registerWorker({ self })` to register itself with the SDK.
45+
46+
## Methods
47+
48+
### `addWorker(worker: Worker)`
49+
50+
Adds a worker to the integration, after it was initialized.
51+
This is useful if you have workers that are initialized at later point in your application's lifecycle.
52+
Note that every worker must call `Sentry.registerWorker({ self })` to register itself with the SDK.

platform-includes/configuration/integrations/javascript.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@
2929
| [`statsigIntegration`](./statsig) | | | | ||
3030
| [`supabaseIntegration`](./supabase) | ||| | |
3131
| [`unleashIntegration`](./unleash) | | | | ||
32+
| [`webWorkerIntegration`](./webworker) | || | | |

0 commit comments

Comments
 (0)