0
# Environment & Browser Detection
1
2
**DEPRECATED**: Import all functions from `@sentry/core` instead of `@sentry/utils`.
3
4
Environment detection utilities for determining runtime capabilities and platform-specific features across browsers and Node.js environments.
5
6
## Capabilities
7
8
### Runtime Environment Detection
9
10
Core functions for detecting the current JavaScript runtime environment.
11
12
```typescript { .api }
13
/**
14
* Detects if code is running in a browser environment
15
* @returns True if running in browser
16
*/
17
function isBrowser(): boolean;
18
19
/**
20
* Detects if code is running in Node.js environment
21
* @returns True if running in Node.js
22
*/
23
function isNodeEnv(): boolean;
24
25
/**
26
* Detects if code is running as a browser bundle (vs. server-side rendering)
27
* @returns True if running as browser bundle
28
*/
29
function isBrowserBundle(): boolean;
30
```
31
32
**Usage Examples:**
33
34
```typescript
35
import { isBrowser, isNodeEnv, isBrowserBundle } from "@sentry/core";
36
37
// Platform-specific initialization
38
if (isBrowser()) {
39
// Browser-only code
40
setupBrowserInstrumentation();
41
registerServiceWorker();
42
} else if (isNodeEnv()) {
43
// Node.js-only code
44
setupNodeInstrumentation();
45
loadServerConfig();
46
}
47
48
// Bundle detection for SSR
49
function initializeApp() {
50
if (isBrowserBundle()) {
51
// Client-side hydration
52
ReactDOM.hydrate(<App />, document.getElementById('root'));
53
} else {
54
// Server-side rendering
55
return ReactDOMServer.renderToString(<App />);
56
}
57
}
58
```
59
60
### Browser API Support Detection
61
62
Functions for detecting support for specific browser APIs and features.
63
64
```typescript { .api }
65
/**
66
* Checks if the Fetch API is available
67
* @returns True if fetch is supported
68
*/
69
function supportsFetch(): boolean;
70
71
/**
72
* Checks if native fetch is available (not polyfilled)
73
* @returns True if native fetch is supported
74
*/
75
function supportsNativeFetch(): boolean;
76
77
/**
78
* Checks if History API is available (pushState, replaceState)
79
* @returns True if History API is supported
80
*/
81
function supportsHistory(): boolean;
82
83
/**
84
* Checks if Referrer Policy is supported
85
* @returns True if referrer policy is supported
86
*/
87
function supportsReferrerPolicy(): boolean;
88
89
/**
90
* Checks if ReportingObserver API is available
91
* @returns True if ReportingObserver is supported
92
*/
93
function supportsReportingObserver(): boolean;
94
```
95
96
**Usage Examples:**
97
98
```typescript
99
import {
100
supportsFetch,
101
supportsNativeFetch,
102
supportsHistory
103
} from "@sentry/core";
104
105
// Conditional network request setup
106
function setupNetworkMonitoring() {
107
if (supportsFetch()) {
108
// Use fetch for network requests
109
addFetchInstrumentation();
110
} else {
111
// Fallback to XMLHttpRequest
112
addXHRInstrumentation();
113
}
114
115
// Prefer native fetch for better performance
116
if (supportsNativeFetch()) {
117
console.log('Using native fetch API');
118
} else {
119
console.log('Using fetch polyfill');
120
}
121
}
122
123
// History API for single-page apps
124
function setupRouting() {
125
if (supportsHistory()) {
126
// Use pushState/replaceState for routing
127
window.addEventListener('popstate', handleRouteChange);
128
} else {
129
// Fallback to hash-based routing
130
window.addEventListener('hashchange', handleHashChange);
131
}
132
}
133
```
134
135
### Error API Support Detection
136
137
Functions for detecting support for various error-related browser APIs.
138
139
```typescript { .api }
140
/**
141
* Checks if DOMError constructor is available
142
* @returns True if DOMError is supported
143
*/
144
function supportsDOMError(): boolean;
145
146
/**
147
* Checks if DOMException constructor is available
148
* @returns True if DOMException is supported
149
*/
150
function supportsDOMException(): boolean;
151
152
/**
153
* Checks if ErrorEvent constructor is available
154
* @returns True if ErrorEvent is supported
155
*/
156
function supportsErrorEvent(): boolean;
157
```
158
159
**Usage Example:**
160
161
```typescript
162
import {
163
supportsDOMError,
164
supportsDOMException,
165
supportsErrorEvent
166
} from "@sentry/core";
167
168
function setupErrorHandling() {
169
// Enhanced error categorization based on support
170
window.addEventListener('error', (event) => {
171
let errorType = 'generic';
172
173
if (supportsErrorEvent() && event instanceof ErrorEvent) {
174
errorType = 'ErrorEvent';
175
} else if (supportsDOMError() && event.error instanceof DOMError) {
176
errorType = 'DOMError';
177
} else if (supportsDOMException() && event.error instanceof DOMException) {
178
errorType = 'DOMException';
179
}
180
181
console.log(`Captured ${errorType}:`, event.error);
182
});
183
}
184
```
185
186
### Function Detection
187
188
Utilities for detecting native vs. wrapped functions.
189
190
```typescript { .api }
191
/**
192
* Checks if a function is a native browser/Node.js function (not wrapped or polyfilled)
193
* @param func - Function to check
194
* @returns True if function appears to be native
195
*/
196
function isNativeFunction(func: Function): boolean;
197
```
198
199
**Usage Example:**
200
201
```typescript
202
import { isNativeFunction } from "@sentry/core";
203
204
function analyzeFunction(fn: Function) {
205
if (isNativeFunction(fn)) {
206
console.log('Native function detected');
207
// Safe to instrument directly
208
return instrumentNative(fn);
209
} else {
210
console.log('Wrapped or polyfilled function detected');
211
// Use more careful instrumentation
212
return instrumentSafely(fn);
213
}
214
}
215
216
// Check if fetch is native or polyfilled
217
if (typeof fetch === 'function') {
218
const isNative = isNativeFunction(fetch);
219
console.log(`Fetch is ${isNative ? 'native' : 'polyfilled'}`);
220
}
221
```
222
223
## Environment Detection Patterns
224
225
### Feature Detection Strategy
226
227
Use feature detection instead of user agent parsing for reliable cross-browser support:
228
229
```typescript
230
import {
231
isBrowser,
232
supportsFetch,
233
supportsHistory,
234
supportsReportingObserver
235
} from "@sentry/core";
236
237
interface BrowserCapabilities {
238
hasNetworkAPI: boolean;
239
hasRouting: boolean;
240
hasReporting: boolean;
241
platform: 'browser' | 'node' | 'unknown';
242
}
243
244
function detectCapabilities(): BrowserCapabilities {
245
return {
246
hasNetworkAPI: isBrowser() && supportsFetch(),
247
hasRouting: isBrowser() && supportsHistory(),
248
hasReporting: isBrowser() && supportsReportingObserver(),
249
platform: isBrowser() ? 'browser' : (isNodeEnv() ? 'node' : 'unknown'),
250
};
251
}
252
```
253
254
### Progressive Enhancement
255
256
Use environment detection for progressive enhancement:
257
258
```typescript
259
import {
260
isBrowser,
261
supportsFetch,
262
supportsReportingObserver
263
} from "@sentry/core";
264
265
class MonitoringClient {
266
private capabilities = detectCapabilities();
267
268
init() {
269
// Base functionality always available
270
this.setupBasicErrorHandling();
271
272
// Progressive enhancement based on environment
273
if (this.capabilities.hasNetworkAPI) {
274
this.setupNetworkMonitoring();
275
}
276
277
if (this.capabilities.hasReporting) {
278
this.setupReportingObserver();
279
}
280
}
281
282
private setupNetworkMonitoring() {
283
if (supportsFetch()) {
284
// Enhanced network monitoring with fetch
285
addFetchInstrumentationHandler(this.handleNetworkEvent);
286
}
287
}
288
289
private setupReportingObserver() {
290
if (supportsReportingObserver()) {
291
// Modern reporting API for deprecations, violations, etc.
292
const observer = new ReportingObserver(this.handleReport);
293
observer.observe();
294
}
295
}
296
}
297
```
298
299
### Conditional Module Loading
300
301
Environment detection for conditional module loading:
302
303
```typescript
304
import { isNodeEnv, isBrowser } from "@sentry/core";
305
306
async function loadPlatformSpecificModules() {
307
if (isNodeEnv()) {
308
// Node.js-specific modules
309
const fs = await import('fs');
310
const path = await import('path');
311
return { fs, path };
312
} else if (isBrowser()) {
313
// Browser-specific modules
314
const { setupServiceWorker } = await import('./serviceWorker');
315
const { initializeAnalytics } = await import('./analytics');
316
return { setupServiceWorker, initializeAnalytics };
317
}
318
319
return {};
320
}
321
```
322
323
## Environment Constants
324
325
```typescript { .api }
326
// Global object reference (window in browser, global in Node.js)
327
declare const GLOBAL_OBJ: typeof globalThis;
328
329
/**
330
* Gets a global singleton instance
331
* @param name - Name of the singleton
332
* @param creator - Function to create the singleton if it doesn't exist
333
* @param obj - Global object to store the singleton (defaults to GLOBAL_OBJ)
334
* @returns The singleton instance
335
*/
336
function getGlobalSingleton<T>(
337
name: string,
338
creator: () => T,
339
obj?: any
340
): T;
341
```
342
343
**Usage Example:**
344
345
```typescript
346
import { getGlobalSingleton, GLOBAL_OBJ } from "@sentry/core";
347
348
// Create a global logger singleton
349
const logger = getGlobalSingleton('__SENTRY_LOGGER__', () => {
350
return new Logger({ level: 'info' });
351
});
352
353
// Access global object consistently
354
console.log('Global object:', GLOBAL_OBJ === window); // true in browser
355
console.log('Global object:', GLOBAL_OBJ === global); // true in Node.js
356
```
357
358
**Migration Note**: All environment detection functions have been moved from `@sentry/utils` to `@sentry/core`. Update your imports accordingly.